我有一个由空行分隔的不同部分的文件,我想根据每个部分第一行的第四个值对所有部分进行升序排序,保持每个部分的主体不进行修改。
输入示例
PT2 energy = 7.135 eV ( -459.5928710 au) ( 57545.0 cm-1) (R=4)
22u22d00 3->6 : -0.535 (0.286)
22202200 4-->6 : -0.344 (0.119)
222u200d 4->8 : 0.256 (0.065)
222u2d00 4->6 : -0.254 (0.065)
R=4 TDM-form-state 1= 0.2702 -0.2855 -0.5610 TDM= 0.69 f: 0.082
PT2 energy = 7.018 eV ( -459.5971543 au) ( 56605.0 cm-1) (R=5)
22u220d0 3->7 : -0.396 (0.156)
222u2d00 4->6 : 0.352 (0.124)
22220ud0 5-->6,7 : 0.326 (0.106)
2222u0d0 5->7 : 0.303 (0.092)
2222u00d 5->8 : 0.271 (0.073)
222ud020 4,5-->7 : 0.267 (0.071)
22u22d00 3->6 : -0.229 (0.052)
R=5 TDM-form-state 1= 0.0860 -0.1785 -0.5446 TDM= 0.58 f: 0.058
PT2 energy = 6.552 eV ( -459.6143027 au) ( 52841.3 cm-1) (R=6)
222u20d0 4->7 : -0.612 (0.374)
2222ud00 5->6 : -0.499 (0.249)
222udud0 4,5-->6,7 : -0.271 (0.074)
R=6 TDM-form-state 1= -0.2916 -0.0544 -2.1475 TDM= 2.17 f: 0.754
输出
PT2 energy = 6.552 eV ( -459.6143027 au) ( 52841.3 cm-1) (R=6)
222u20d0 4->7 : -0.612 (0.374)
2222ud00 5->6 : -0.499 (0.249)
222udud0 4,5-->6,7 : -0.271 (0.074)
R=6 TDM-form-state 1= -0.2916 -0.0544 -2.1475 TDM= 2.17 f: 0.754
PT2 energy = 7.018 eV ( -459.5971543 au) ( 56605.0 cm-1) (R=5)
22u220d0 3->7 : -0.396 (0.156)
222u2d00 4->6 : 0.352 (0.124)
22220ud0 5-->6,7 : 0.326 (0.106)
2222u0d0 5->7 : 0.303 (0.092)
2222u00d 5->8 : 0.271 (0.073)
222ud020 4,5-->7 : 0.267 (0.071)
22u22d00 3->6 : -0.229 (0.052)
R=5 TDM-form-state 1= 0.0860 -0.1785 -0.5446 TDM= 0.58 f: 0.058
PT2 energy = 7.135 eV ( -459.5928710 au) ( 57545.0 cm-1) (R=4)
22u22d00 3->6 : -0.535 (0.286)
22202200 4-->6 : -0.344 (0.119)
222u200d 4->8 : 0.256 (0.065)
222u2d00 4->6 : -0.254 (0.065)
R=4 TDM-form-state 1= 0.2702 -0.2855 -0.5610 TDM= 0.69 f: 0.082
我尝试过
sort -n -k4 file
但这对所有文件进行操作并破坏这些部分
答案1
使用任何 awk、排序和剪切:
$ awk -v OFS='\t' '!pNF{val=$4} {print val, NR, $0; pNF=NF} END{if (pNF) print val, NR+1, ""}' file |
sort -k1,1n -k2,2n |
cut -f3-
PT2 energy = 6.552 eV ( -459.6143027 au) ( 52841.3 cm-1) (R=6)
222u20d0 4->7 : -0.612 (0.374)
2222ud00 5->6 : -0.499 (0.249)
222udud0 4,5-->6,7 : -0.271 (0.074)
R=6 TDM-form-state 1= -0.2916 -0.0544 -2.1475 TDM= 2.17 f: 0.754
PT2 energy = 7.018 eV ( -459.5971543 au) ( 56605.0 cm-1) (R=5)
22u220d0 3->7 : -0.396 (0.156)
222u2d00 4->6 : 0.352 (0.124)
22220ud0 5-->6,7 : 0.326 (0.106)
2222u0d0 5->7 : 0.303 (0.092)
2222u00d 5->8 : 0.271 (0.073)
222ud020 4,5-->7 : 0.267 (0.071)
22u22d00 3->6 : -0.229 (0.052)
R=5 TDM-form-state 1= 0.0860 -0.1785 -0.5446 TDM= 0.58 f: 0.058
PT2 energy = 7.135 eV ( -459.5928710 au) ( 57545.0 cm-1) (R=4)
22u22d00 3->6 : -0.535 (0.286)
22202200 4-->6 : -0.344 (0.119)
222u200d 4->8 : 0.256 (0.065)
222u2d00 4->6 : -0.254 (0.065)
R=4 TDM-form-state 1= 0.2702 -0.2855 -0.5610 TDM= 0.69 f: 0.082
否则,只需使用 GNU awk 来处理数组的数组,并使用sorted_in:
awk '
BEGIN { RS=""; ORS="\n\n" }
{ recs[$4][++cnt[$4]] = $0 }
END {
PROCINFO["sorted_in"] = "@ind_num_asc"
for (val in recs) {
for (i=1; i<=cnt[val]; i++) {
print recs[val][i]
}
}
}
' file
循环的目的cnt[]
是,如果/当相同的值(例如7.135
)在不同输入记录的第四个字段中多次出现时,输出将保留该键值的输入顺序。或者,在读取输入时,您可以通过字符串连接获得相同的结果,例如仍然使用 GNU awk 进行排序:
awk '
BEGIN { RS=""; ORS="\n\n" }
{ recs[$4] = recs[$4] $0 ORS }
END {
PROCINFO["sorted_in"] = "@ind_num_asc"
for (val in recs) {
printf "%s", recs[val]
}
}
' file
仅使用 gawk 的方法的缺点是它们必须将整个文件存储在内存中,并且无法移植到没有 gawk 的系统。顶部的 awk+sort+cut 脚本具有高度可移植性,只有“sort”必须一次处理整个文件,并且它被设计为使用需求分页等来处理大文件,因此不太可能一个比 gawk 更大的文件的问题。
答案2
sort
是面向线的。这里你需要阅读“段落”中的文件。
这可以通过一个非常短的 GNU awk 程序来完成:
gawk -v RS= -v ORS='\n\n' '
{section[$4] = $0}
END {
PROCINFO["sorted_in"] = "@ind_num_asc"
for (key in section) print section[key]
}
' file
将 RS 变量(记录分隔符)设置为空字符串会读取包含空行分隔记录的文件。每条记录都存储在一个数组中,并通过排序键进行索引。
神奇的 PROCINFO 行告诉 gawk 在遍历数组时按索引对数组进行数字排序。