【问题标题】:Redirect input for gawk to a system command将 gawk 的输入重定向到系统命令
【发布时间】:2015-04-10 05:32:44
【问题描述】:

通常 gawk 脚本会处理其标准输入的每一行。是否可以在脚本中指定一个系统命令,使用脚本其余部分中命令输出的每一行的过程?

例如考虑以下简单的交互:

$ { echo "abc"; echo "def"; } | gawk '{print NR ":" $0; }'
1:abc
2:def

我想在不使用管道的情况下获得相同的输出,而是将 echo 命令指定为系统命令。

我当然可以使用管道,但这会迫使我要么使用两个不同的脚本,要么在 bash 脚本中指定 gawk 脚本,我正试图避免这种情况。

更新

前面的例子不太能代表我的用例,这个比较接近:

$ { echo "abc"; echo "def"; } | gawk '/d/ {print NR ":" $0; }'
2:def

更新 2

一个并行的shell脚本如下。如果没有exec 行,脚本将从stdin 读取;使用 exec 它将使用该行作为输入的命令:

/tmp> cat t.sh
#!/bin/bash

exec 0< <(echo abc; echo def)
while read l; do
  echo "line:" $l
done
/tmp> ./t.sh 
line: abc
line: def

【问题讨论】:

标签: awk


【解决方案1】:

我相信你要找的是getline

awk '{ while ( ("echo abc; echo def" | getline line) > 0){ print line} }' <<< ''
abc
def

调整答案给你第二个例子:

awk '{ while ( ("echo abc; echo def" | getline line) > 0){ counter++; if ( line ~ /d/){print counter":"line} } }' <<< ''
2:def

让我们分解一下:

awk '{ 
       cmd = "echo abc; echo def"

       # line below will create a line variable containing the ouptut of cmd
       while ( ( cmd | getline line) > 0){ 

          # we need a counter because NR will not work for us
          counter++; 

          # if the line contais the letter d
          if ( line ~ /d/){ 
             print counter":"line
          } 
        } 
    }' <<< ''
    2:def

【讨论】:

  • 这非常适合我的示例,但我无法弄清楚如何使用其他 awk 结构。我将用一个更复杂的例子来更新我的问题。
  • 顺便说一句,&lt;&lt;&lt; 是做什么的?
  • awk 需要 STDIN 才能工作,这只是发送空字符串,与 echo "" | awk {dosomething} 相同
  • 我想避免一系列if/else if。我将使用并行使用 shell 脚本的示例对问题进行最后一次更新
  • Fwiw,如果您将其设为 BEGIN 块,则不需要 &lt;&lt;&lt; ''
【解决方案2】:

从你所有的 cmets 看来,你想要的是:

$ cat tst.awk
BEGIN {
    if ( ("mktemp" | getline file) > 0 ) {
        system("(echo abc; echo def) > " file)
        ARGV[ARGC++] = file
    }
    close("mktemp")
}

{ print FILENAME, NR, $0 }

END {
    if (file!="") {
        system("rm -f \"" file "\"")
    }
}

$ awk -f tst.awk
/tmp/tmp.ooAfgMNetB 1 abc
/tmp/tmp.ooAfgMNetB 2 def

但老实说,我不会这样做。你正在用 awk 擅长的东西(操作文本)来混合 shell 擅长的东西(创建/销毁文件和进程)。

【讨论】:

  • 这几乎正是我写的时候的意思,我将把它重定向到一个临时文件。你很正确,这是在滥用 awk,我的选择是(i)使用带有内联 awk 脚本的 shell 脚本(ii)使用上述方法。我将不得不决定语法着色对我有多重要:)
  • @MiserableVariable 实际上只是在正确方式或错误方式之间做出决定。 UNIX 的哲学是拥有一堆小工具,每个工具都做好一件事,以及一个外壳来对它们的调用进行排序。在您可以做的事情上,工具和外壳之间存在一些重叠,但如果您为每项工作坚持使用正确的工具,您每次都会获得更加简洁、强大和高效的结果。
  • 相对而言,我想指出的是,没有这样的哲学体系可以完全一致和正确,并且在某些情况下需要打破规则。您认为简单的事情——在某些情况下,使用 shell 脚本和单独的 awk 脚本可能会变得不必要地复杂。无论如何,SO 在论坛上讨论主观意见,这是边缘主观的。我将继续感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 2010-09-09
  • 2023-03-18
  • 2022-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多