awk将命令输出保存到变量中

4

我需要对某个文件的每一行执行一个命令。例如:

file1.txt 100 4
file2.txt 19 8

因此,我的awk脚本需要执行类似以下内容的操作:
command $1 $2 $3

需要执行命令 $1 $2 $3 并保存输出结果,但不能使用 system()getline 函数(如果使用这些函数,则无法将输出作为管道传递)。此问题的限制是只能使用 awk。 (我已经有一个使用 bash 脚本和 awk 的解决方案了...但我只想使用 awk...只是为了更多地了解它)

2个回答

3
使用 getline 有什么问题吗?
$ ./test.awk test.txt
# ls -F | grep test
test.awk*
test.txt
# cat test.txt | nl 1 ls -F | grep test 2 cat test.txt | nl 3 cat test.awk
# cat test.awk #!/usr/bin/awk -f { cmd[NR] = $0 while ($0 | getline line) output[NR] = output[NR] line RS } END { for (i in cmd) print "# " cmd[i] ORS output[i] }

这是一个Bash脚本。当我使用getline时,无法将命令进行管道传输,例如cat file | process parameters,我只能得到cat file。我正在尝试更加清晰的方式来完成这个任务... - llazzaro
最后10行回答了我的问题。 - llazzaro
嗯,我以为这很明显是演示脚本在自身上运行,但也许不是。 - ephemient

0

Awk的system()函数将字符串传递给/bin/sh,因此您可以使用重定向运算符,例如">file.out"。

awk '{system("command " $1 " " $2 " " $3 ">" $1 ".out");}'

编辑:好的,你的意思是将其保存到awk变量中。ephemient是正确的方向。这就是awk的getline所做的事情,就像shell/perl中的反引号或$(cmd)一样。实际上,谷歌搜索awk反引号找到了这个: http://www.omnigroup.com/mailman/archive/macosx-admin/2006-May/054665.html

你说你不能使用getline,因为那样就无法进行管道操作。但是你可以通过使用tee和文件描述符技巧来解决这个问题。如果/bin/sh是bash,则可以使用以下方法:

{ "set +o posix; command " $1 " " $2 " "  $3  " | tee >(grep foo)"  | getline var; print toupper(var); } # bash-only, and broken.

set +o posix 是必要的,因为 awk 将 bash 作为 sh 运行,在读取其启动文件后进入 posix 模式。嗯,我没有成功让它工作,并且它仍然需要 bash。

好的,这个可以:


    $ touch foo bar
    $ echo "foo bar" | 
      awk '{ "{ ls " $1 " " $2 " "  $3  " | tee /dev/fd/10 | grep foo > /dev/tty; } 10>&1"  | getline var; print toupper(var); }'
    foo
    BAR

我的实际解决方案是这样的,但我无法将命令的输出发送到变量。 - llazzaro
你可以使用后续的 readline [...] < $1 ".out" 循环将输出读回来。不要忘记在完成后进行清理... - ephemient
我使用了一些文件描述符重定向来同时进行管道和getline操作。这样做是否满足您的需求? - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接