系统调用、AWK 和引入外部输入

mon*_*ksy 4 scripting awk text-processing

awk '{ TEMPVAR="/usr/bin"; printf("%s", system("ls $TEMPVAR")); }' empty
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我试图将变量TEMPVAR引入system调用中。我该怎么做?

我的目标是:我试图date -d $0 +%ssystem文件的每一行发生的调用中使用。但是,我正在努力解决如何将该$0值放入系统调用中。

Sté*_*las 8

awk可以使用ENVIRON特殊数组访问环境变量。然而,尽管可以将值分配给该数组的元素,但是并不在所执行的命令的环境中通过awksystem| getlineprint |。这ENVIRON阵仅用于awk得到它是通过环境变量的值。

您可以这样做:system("ls " var),但要注意传递给awk's system()(or print |or | getline)的字符串实际上是作为参数传递给 的sh -c,因此它被解释为 shell 代码。

例如,如果awk var变量包含foo;rm -rf /,它不会告诉ls列出调用的文件"foo;rm -rf /",而是列出调用的文件foo,然后rm将运行命令。

因此,您可能需要转义该var变量中所有 shell 特有的字符。

这可以通过例如:

awk '
  function escape(s) {
    gsub(/'\''/, "&\\\\&&", s)
    return "'\''" s "'\''"
  }
  {
    cmd = "date -d " escape($0) " +%s"
    cmd | getline seconds
    close(cmd)
    print seconds
  }'
Run Code Online (Sandbox Code Playgroud)

虽然这意味着date每行运行一个 shell 和一个命令,但您也可以使用 shell 本身来读取文件:

while IFS= read <&3 -r line; do
  date -d "$line" +%s
done 3< the-file
Run Code Online (Sandbox Code Playgroud)

  • 对于想知道为什么使用这么多引号和反斜杠的未来读者来说,这是因为代码段 * 也是一个 **shell 命令*。您基本上需要做的是在参数周围放置单引号,并将参数中的单引号替换为`'\''`(结束字符串,插入`\'`,继续字符串)。在 AWK 脚本(文件)中,使用 `gsub(/'/, "'\\''", s) 就足够了;return "'" s "'";`,但对于“单行”命令,单引号和反斜杠必须再次转义,如 Stephane 所示。 (2认同)