我有以下bash脚本,它从文件中提取数字列表。我想维护它们被拉出顺序的日志(这是重要的信息)。所以我得到了一些帮助(可能来自我在这里找到的一个例子)将信息转储到数组中,排序并输出信息。
if [ ! -z "$sort" ]; then
if [[ $sort == ascending ]]; then
gawk '/SCF Done/\
{c++; list[$5]=c}
END {
asorti(list,energies);
for (i=1;i<=c;i++)
printf("%s%s%d\n",energies[i]," - Optimization Step #",list[energies[i]])
print "Total Optimization Steps: "c}
' "$1"
唯一的问题是,我发现存储在行$5
字段中的值有可能重复。因此,在初始构建数组list[$5]
期间,此值可能是非唯一的,因此先前的c
值会被覆盖。我想到了一些事情(将$5
的值乘以一些随机数,然后再将其重新划分),但如果已经建立(并且更有效)的方法,我不会感到惊讶处理这个我不知道的问题。
以下是grep "SCF Done"
SCF Done: E(UM11L) = -1267.67892101 A.U. after 41 cycles
SCF Done: E(UM11L) = -1267.64771239 A.U. after 43 cycles
SCF Done: E(UM11L) = -1267.67892101 A.U. after 39 cycles
SCF Done: E(UM11L) = -1267.67892578 A.U. after 24 cycles
SCF Done: E(UM11L) = -1267.67892051 A.U. after 24 cycles
SCF Done: E(UM11L) = -1267.67892201 A.U. after 22 cycles
我切换到gawk格式的全部原因是因为我想拉出那些中间数字,然后还创建一个格式化的输出,如下所示。我最初使用了一个简单的grep "SCF Done"
语句,但随后获得格式化,排序等等,开始成为一个相当麻烦的语句。事实仍然是相同的,我希望能够按这些数字排序,同时保留数字和优化步骤之间的相关性(如下所示)。但这些数字并不总是唯一的。
-1267.67892101 - Optimization Step #1
-1267.64771239 - Optimization Step #2
-1267.67892101 - Optimization Step #3
-1267.67892578 - Optimization Step #4
-1267.67892051 - Optimization Step #5
-1267.67892201 - Optimization Step #6
答案 0 :(得分:2)
为什么要使用gawk
而不是sort
进行排序?
我从你的代码片段中找不到你要完成的任务,但也许:
grep 'SCF Done' "$1" | cut -f5 | cat -n | sort -k 2
我明白了。如何调用排序而不是使用awk的数组排序。
awk '
/SCF Done/ {
printf "%s - Optimization step #%d\n", $5, ++n | "sort"
}
END {
close("sort")
print "total steps:", n
}
' file
看起来像:
-1267.64771239 - Optimization step #2
-1267.67892051 - Optimization step #5
-1267.67892101 - Optimization step #1
-1267.67892101 - Optimization step #3
-1267.67892201 - Optimization step #6
-1267.67892578 - Optimization step #4
total steps: 6
答案 1 :(得分:0)
我错过了排序发挥作用的地方吗?如果您担心重复行,只需跳过该行,如果它与您上一行相同:
$ awk
'END { print "total steps: " count }
/SCF Done/ {
if ( prev5 == $5 ) {
continue # Skip duplicate line
}
count++
printf "%s - Optimization step #%d\n", $5, count
prev5 = $5
}'
如果你真的不希望重复一行,请使用数组存储$ 5的值作为数组的键。然后,您可以使用该数组来查看是否曾经击中该行。 awk
中的所有数组都是哈希值:
$ awk
'END { print "total steps: " count }
{
if ( $0 ~ /SCF Done/ ) {
if ( prev[$5] == 1 ) {
continue # Seen that value of $5 before. Skip
}
count++
printf "%s - Optimization step #%d\n", $5, count
prev[$5] = 1 # Mark that you've printed $5 out
}
}'