我想按字符串分隔的部分对文件进行排序,但它是 awk 中处理的较大部分。
我读到可以在定界符之间存储行,然后使用 asort 进行排序,但我需要使用第二列对其进行排序。
我决定将分隔符之间的输出存储在变量中(k),然后使用管道将变量的值传递到命令中|,最后读取输出,处理它并打印。
然而,使用print variable|"sort -k2,2"|getline v
使得获取线(?) 卡住了。
我可以执行命令更丑使用函数的方式system()
,但后来我认为我需要使用 echo 将变量传递给命令,并且输出不存储在变量 v 中,而是存储在错误代码中。
$ awk 'BEGIN{ cmd="sort -k2,2"; k="1\tB\n2\tA"; v=system("echo \""k"\" | "cmd); print "OK: "v}'
2 A
1 B
OK: 0
这更好print k|command
使用(removing )的方式|getline v
执行命令,但print "OK"
在子命令的输出之前完成。输出也不存储在变量中v。
$ awk 'BEGIN{ cmd="sort -k2,2"; k="1\tB\n2\tA"; print k|cmd; print "OK: "v}'
OK:
2 A
1 B
如何将命令输出存储在变量中,或者至少等待上一个子命令完成后再继续?
答案1
这是你想要做的吗(使用 GNU awk 来协进程)?
$ cat tst.awk
BEGIN {
cmd = "sort -k2,2"
k = "1\tB\n2\tA"
print k |& cmd
close(cmd, "to")
while ((cmd |& getline line) > 0) {
v = v line ORS
}
close(cmd)
print "OK:"
printf "%s", v
}
$ awk -f tst.awk
OK:
2 A
1 B
由于上面使用了 GNU awk (并且您已经提到过分类()在你的问题中,这是仅限 gawk 的)并且 gawk 已经内置了排序,你可能不需要这样做,例如使用排序入sort
而不是像上面那样为每次调用创建一个子 shell :
$ cat tst.awk
BEGIN {
k = "1\tB\n2\tA"
split(k,lines,/\n/)
for (i in lines) {
lines[i] = gensub(/[^\t]*\t([^\t]+)/,"\\1\t&",1,lines[i])
}
PROCINFO["sorted_in"] = "@val_str_asc"
for (i in lines) {
v = v gensub(/[^\t]\t/,"",1,lines[i]) ORS
}
print "OK:"
printf "%s", v
}
$ awk -f tst.awk
OK:
2 A
1 B
但我认为这是您尝试执行的一些更困难的任务的简化版本,这些任务实际上需要协进程。
答案2
任何对本文中描述的问题的解决方案感兴趣的人评论:
awk 正在处理其他命令(即 squeue)的输出,我不需要有关其他用户作业的完整信息,并且我想折叠它们,但我仍然需要将提交的作业保留在正确的位置才能知道,当他们有资格参加跑步时。
alias squeue="_squeue() {
/usr/bin/squeue --format=\"%.8i %.9P %.20j %.10u %.2t %.10M %.10L %.6D %R\" \$@ \
| awk '
BEGIN { cmd=\"sort -k2,2 -k5,5 -k4,4\" }
function sort(buf) {
sorted=\"\"
gsub(\"^\"ORS\"*|\"ORS\"{2,}|\"ORS\"*$\", \"\", buf)
if (length(buf)>0) {
print buf |& cmd
close(cmd, \"to\")
while ((cmd |& getline line) > 0) {
sorted = sorted line ORS
}
close(cmd)
}
return sorted
}
NR <= 1 { print; next }
/'\$USER'/ {
printf(\"%s\", sort(buf))
buf=\"\"
print
partition=\$2; user=\$4; st=\$5;
next
}
{ buf = buf ORS \$0 }
END {
printf(\"%s\", sort(buf))
}
' \
| awk '
BEGIN { partition=\"\"; user=\"\"; st=\"\"; c=0; n=0; }
function print_count() {
if(c>0) { print \" (count: \"c\" jobs, \"n\" nodes)\"; c=0; n=0; }
}
NR <= 1 { print \$0; next }
/'\$USER'/ {
print_count()
print;
next
}
\$2!=partition || \$4!=user || \$5!=st {
print_count()
printf(\"%-98s\", substr(\$0,0, 98));
partition=\$2; user=\$4; st=\$5;
}
{ n+=\$8; c++ }
END {
print_count()
}' \
| sed '/(count: .*)$/{s/.*/\x1b[90m&\x1b[0m/p;d};
/\s'\$USER'\s\+[^R]\+\s/{s/.*/\x1b[1m&\x1b[0m/p;d}'
}
_squeue"