在 awk 中使用 shell 变量

Nic*_*las 10 bash awk variable

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

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

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

MyScript.sh pattern
Run Code Online (Sandbox Code Playgroud)

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

当我尝试调试我的脚本时

bash -x MyScript.sh pattern
Run Code Online (Sandbox Code Playgroud)

这是输出:

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

$vawk变量似乎是空的。

任何的想法?

jw0*_*013 10

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

awk -v vawk="$1" '$0 ~ vawk { c++ } # ...'
#                      ^ awk variable syntax
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`awk` 扩展了`$1` 中类似C 的转义序列,因此如果`$1` 可能包含反斜杠字符(正则表达式常见),则该方法不起作用。您可以改用`ENVIRON` awk 特殊数组。 (2认同)

Sté*_*las 9

这里复制现在作为重复问题关闭,因为它包含关于 awk 变量传递限制的警告,人们可能会觉得这很有用。

一个shell变量就是这样:一个外壳变量。如果你想把它变成一个awk变量,你需要这样的语法:

awk -v x="$x" '$2 == x {print $1}' infile
Run Code Online (Sandbox Code Playgroud)

或者

awk '$2 == x {print $1}' x="$x" infile
Run Code Online (Sandbox Code Playgroud)

但是,那些遇到了一个问题:转义序列在其中展开(在 GNU awk4.2 或更高版本中,如果$x以 开头@/和结尾/,则将其视为正则表达式类型的变量)。

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

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

x="$x" awk '$2 == ENVIRON["x"] {print $1}' infile
Run Code Online (Sandbox Code Playgroud)

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

awk 'BEGIN {x = ARGV[1]; delete ARGV[1]}
  $2 == x {print $1}' "$x" infile
Run Code Online (Sandbox Code Playgroud)