【问题标题】:How can I pass variables from awk to a shell command?如何将变量从 awk 传递到 shell 命令?
【发布时间】:2014-01-05 23:06:25
【问题描述】:

我试图在 awk 中为文件的每一行运行一个 shell 命令,而 shell 命令需要一个输入参数。我尝试使用system(),但它无法识别输入参数。

这个文件的每一行都是一个文件的地址,我想运行一个命令来处理那个文件。因此,对于一个简单的示例,我想对每一行使用“wc”命令并将$1传递给 wc。

awk '{system("wc $1")}' myfile

【问题讨论】:

  • 您为什么认为 awk 是适合这项工作的工具?似乎xargs 或简单的shell while read line 循环会更好更容易。
  • 另一方面:为什么您认为 wc 是适合这项工作的工具?似乎 awk 内置变量和函数会更好更容易?

标签: shell awk parameter-passing


【解决方案1】:

你很接近。您必须将命令行与 awk 变量连接起来:

awk '{system("wc "$1)}' myfile

【讨论】:

  • 谢谢,这行得通!但还有一个问题?我们可以将输出分配给一个新变量吗?
  • 这是这个作业的错误语法,它是 system() 的错误应用程序,打印没有按照您的想法执行,不,您不能分配系统的输出( ) 调用 awk 变量,您在评论中发布的内容将 system() 的返回代码分配给变量。是时候喝杯咖啡了@Kent!
  • @EdMorton 是的!系统返回状态码.....我被 vimscripts 的system()...:( . cmd|getline var 应该读取输出......这个答案/评论对于变量部分不正确.
  • system() 部分也不正确——应该是system("wc \"" $1 "\"")
  • 传2个参数怎么处理?
【解决方案2】:

您无法获取 awk system() 调用的输出,您只能获取退出状态。使用getline/pipegetline/variable/pipe 构造

awk '{
    cmd = "your_command " $1
    while (cmd | getline line) {
        do_something_with(line) 
    }
    close(cmd)
}' file

【讨论】:

  • +1 获取shell命令输出的正确方法,但通常创建变量的语法是cmd = "your_command \"" $1 ""\",因此在执行cmd时会引用参数并且您需要测试对于 getline 的结果大于零,否则如果失败,您将陷入无限循环。
  • +1 。 OP,如果您需要将输出存储在 var 中,也请接受这个答案。我的 var 分配不正确。
  • @EdMorton 我想你的意思是cmd = "your_command \"" $1 "\""
  • @jaygooby 是的,我知道,很好发现。
【解决方案3】:

仅供参考,这里是如何使用 awk 处理名称存储在文件中的文件(在此示例中提供类似 wc 的功能):

gawk '
NR==FNR { ARGV[ARGC++]=$0; next }
{ nW+=NF; nC+=(length($0) + 1) }
ENDFILE { print FILENAME, FNR, nW, nC; nW=nC=0 }
' file

以上使用 GNU awk 作为 ENDFILE。对于其他 awk,只需将值存储在数组中并在 END 部分的循环中打印。

【讨论】:

    【解决方案4】:

    或者在 bash 中使用管道 | 然后使用 awk 的 getline 在变量中检索输出,就像这样

     zcat /var/log/fail2ban.log* | gawk  '/.*Ban.*/  {print $7};' | sort | uniq -c | sort | gawk '{ "geoiplookup " $2 "| cut -f2 -d: " | getline geoip; print $2 "\t\t" $1 " " geoip}'
    

    该行将使用 geoip-bin 包从您的服务器打印所有被禁止的 IP 及其来源(国家/地区)。

    那条线的最后一部分是影响我们的那部分:

    gawk '{ "geoiplookup " $2 "| cut -f2 -d: " | getline geoip; print $2 "\t\t" $1 " " geoip}'
    

    它只是说:运行命令"geoiplookup 182.193.192.4 | -f2 -d:"(您可能猜到$2被替换)并将该命令的结果放入geoip(| getline geoip位)。接下来,在geoip 变量中打印一些东西和任何东西。

    完整的例子和结果可以在我写的一篇文章here找到。

    【讨论】:

      【解决方案5】:

      我会建议另一种解决方案:

      awk '{print $1}' myfile | xargs wc
      

      不同之处在于它使用多个参数执行一次wc。它通常有效(例如,使用 kill 命令)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-28
        • 2017-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-08
        • 1970-01-01
        相关资源
        最近更新 更多