在awk中使用shell变量


8

这是我的脚本(查找包含指定模式的文件):

find . -type f \
    -exec awk -v vawk="$1" '/'"$vawk"'/ {c++} c>0 { print ARGV[1]; exit 0 } END { if (! c) {exit 1}}' \{\} \;

我想将我的脚本与参数§一起使用:

MyScript.sh pattern

我的问题是我无法将$1变量放入awk

当我尝试调试脚本时

bash -x MyScript.sh pattern

这是输出:

+ find . -type f -exec awk -v vawk=pattern '// {c++} c>0 {print ARGV[1] ; exit 0 } END { if (! c) {exit 1}}' '{}' ';'

$vawk变量似乎为空。

任何的想法?

Answers:


7

您似乎混淆了awk变量和shell变量。 awk -v vawk="$1"创建一个名为的awk变量vawk,但您正在尝试使用shell语法($vawk)。这不起作用,因为外壳没有名为的变量vawk。我想你想要的是

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax

1
请注意,在中awk扩展了类似于C的转义序列$1,因此,如果$1可能包含反斜杠字符(对于正则表达式很常见),则该方法将不起作用。您可以改用ENVIRONawk特殊数组。
斯特凡Chazelas

6

转载自此,现在已关闭,作为重复的问题,因为它包括警告awk变量传递的限制,这可能会有用。

一个shell变量就是:一个shell变量。如果要将其转换为awk变量,则需要以下语法:

awk -v x="$x" '$2 == x {print $1}' infile

要么

awk '$2 == x {print $1}' x="$x" infile

但是,这些问题有一个问题:转义序列会在其中进行扩展(并且在GNU awk4.2或更高版本中,如果$x以开头@/和结束于/,则将其视为变量的regexp类型)。

因此,例如,如果shell变量包含两个字符反斜杠n,则awk变量最终将包含换行符(对于gawk 4.2+,如果包含@/foo/,则awk变量将包含foo并且类型为regexp)。

另一种方法(但是像这样-v需要POSIX awk或nawk(与/bin/awkSolaris中仍然存在的1970年代的awk相反))是使用环境变量:

x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile

另一种方法(仍然使用较新的awk)是在awk中使用ARGV阵列:

awk 'BEGIN {x = ARGV[1]; delete ARGV[1]}
  $2 == x {print $1}' "$x" infile
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.