有两种方法可以通过命令行设置awk vars?


10

我注意到一个O'Reilly的awk示例(1997年),该示例通过在程序文本之后的命令行上进行设置来分配awk变量。它确实有效,但是我在man / info awk中找不到此语法。我刚刚错过了吗?被描述过...?我在手册中看到的唯一语法是该-v选项。

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

输出: cat dog

Answers:


11

它实际上在POSIX中awk(我相信也链接到POSIX 2008,以前的版本中也有)。-v在“ 选项”部分中进行了说明,另一种方式在“ 操作数”部分中。

-v在文件名的末尾传递和传递之间是有区别的:

  • -v

应用程序应确保赋值参数的形式与赋值操作数相同。指定的变量分配应在执行awk程序之前发生,包括与BEGIN模式相关的动作(如果有)。可以指定多次出现此选项。

  • 与文件名混合:

[...]每个此类变量分配都应在处理以下文件(如果有)之前进行。因此,第一个文件参数之前的赋值应在BEGIN动作(如果有)之后执行,而最后一个文件参数之后的赋值应在END操作(如果有)之前发生。如果没有文件参数,则应在处理标准输入之前执行分配。

例:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four

哇!这增加了一些有趣的控制点...它一定会派上用场。谢谢...
Peter.O 2012年

1
我最初的“哇!” 仍然有效,但是通过进一步研究Arcege的答案已经有所 调整 ...我用一个名为“ var = three”的真实文件对其进行了测试... awk优先考虑将其作为变量赋值 ...这有一个主要的推论,即。在所有情况下,如果文件名采用这种形式,它将被忽略并设置变量。看来避免这种冲突的唯一方法是确保当前工作目录的文件名必须始终加上前缀及其相对路径:./var=three
Peter.O 2012年

@ Peter.O,是的,这也是-v引入语法的原因之一。-v今后,您应该将语法视为进行赋值的首选方法。
dubiousjim 2012年

@ Peter.O,优良的有关“疑难杂症”,如果文件名是一个有效的变量赋值点。如果您使用包含文件名的shell变量并将其作为参数传递给awk,则可以使用以下捕获:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
通配符

4

这是在中外部设置变量的一种旧样式awk。它是模棱两可的(如果文件名叫foo=cat),那么以后的版本中添加了一个-v选项。它可能应该可以向后兼容,但是您不能保证。正如我所说,该-v选项是较新的,因此并非所有版本awk都支持它。


您对文件名冲突的可能性的评论很好...我已经对其进行了测试,这绝对是一个问题。我在对Mat的答案的评论中写了更多内容。Thansk着重强调了此问题(+1)
Peter.O 2012年

2
实际上,如[Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v`中所述,参数赋值的生效时间不同。同样-v是在POSIX和应该存在,但在所有的最古老的awk实现。使用./或确保文件名包含非标识符字符可能是消除歧义的最可靠方法。
2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.