将 awk 变量传递给命令并读取输出

将 awk 变量传递给命令并读取输出

我想按字符串分隔的部分对文件进行排序,但它是 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"

相关内容