Fel*_*sto 3 bash text-processing text-formatting
我有一个如下所示的文件:
# Time-averaged data for fix avetimeall
# TimeStep Number-of-rows
# Row c_gyrationchunkall
1000 3
1 2.09024e-14
2 4.88628
3 5.69321
2000 3
1 2.10518e-14
2 8.33702
3 8.83162
3000 3
1 1.96656e-14
2 12.1396
3 11.5835
...
Run Code Online (Sandbox Code Playgroud)
在我的文件中,前三行始终是标题。在标题之后,我的文件列出了相同大小的数据块,每个数据块都以标签子标题开头。我想重新组织文件中的数据,以便将每个块中的数据发送到以该块标签的相关部分开始的行中,然后列出该块的相关数据值,所有数据都用空格分隔开。作为示例,我想将上面的示例转换为:
# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835
...
Run Code Online (Sandbox Code Playgroud)
我如何在 Bash 中执行此操作?我有一些 Bash 经验,但恐怕不足以快速处理这个问题......
使用任何 awk,无论3
块中的行数是否可以变化:
$ awk '
NR == 2 { $3=""; saved=$0; next }
NR == 3 { $0=saved $3 }
NR < 4 { print; next }
!numLines {
numLines = $2
printf "%s%s", $1, OFS
next
}
{ printf "%s%s", $2, (--numLines ? OFS : ORS) }
' file
# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835
Run Code Online (Sandbox Code Playgroud)
继Xavier Gs 回答下有关可读性风格偏好的讨论之后,这里有一个 awk 脚本,其编写风格与 shell 脚本相同(并包含在 shell 脚本中,因此它在外部的行为方式相同),但它将运行比 shell 脚本快*几个数量级,并且比 shell 脚本更健壮和可移植:
$ cat ./script_filename
#!/usr/bin/env bash
awk '
BEGIN {
# Reformat comments:
getline first_line
print first_line
getline; split($0,line2)
getline; split($0,line3)
printf "# %s %s\n", line2[2], line3[3]
# Reformat data:
while ( getline > 0 ) {
timestep=$1; number_of_rows=$2
printf "%s", timestep
for ( i=1; i<=number_of_rows; i++ ) {
getline; row_value=$NF
printf " %s", row_value
}
print ""
}
}
'
Run Code Online (Sandbox Code Playgroud)
$ ./script_filename < input
# Time-averaged data for fix avetimeall
# TimeStep c_gyrationchunkall
1000 2.09024e-14 4.88628 5.69321
2000 2.10518e-14 8.33702 8.83162
3000 1.96656e-14 12.1396 11.5835
Run Code Online (Sandbox Code Playgroud)
* 以下是在包含 90,000 条 OP 记录的文件上运行 bash 脚本与上述 awk 脚本的第三次运行计时结果:
$ time ./script_bash < file > /dev/null
real 0m9.425s
user 0m5.062s
sys 0m4.139s
Run Code Online (Sandbox Code Playgroud)
$ time ./script_awk < file > /dev/null
real 0m0.265s
user 0m0.171s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
741 次 |
最近记录: |