如何在awk脚本中使用shell变量?

我发现了一些向awk脚本传递外部shell变量的方法,但我对'"感到困惑。

首先,我试着用一个shell脚本。

$ v=123test
$ echo $v
123test
$ echo "$v"
123test

然后尝试了awk。

$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123

为什么会有这样的差别?

最后我试了一下这个。

$ awk 'BEGIN{print " '$v' "}'
$  123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1:             ^ unexpected newline or end of string 

我对此感到困惑。

解决办法

将shell变量放入awk中。

可以用几种方法来完成。有些方法比其他方法更好。这应该涵盖了其中的大部分。 如果你有什么意见,请在下面留言。


使用-v(最好的方法,最容易携带)

使用-v选项:(P.S. 在-v后面加一个空格,否则会降低便携性。例如,awk -v var=而不是awk -vvar=)

variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two

这应该与大多数 "awk "兼容,而且变量在 "BEGIN "块中也是可用的。

如果你有多个变量。

awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'

警告。 正如Ed Morton所写的,转义序列会被解释,所以t变成了真正的tab,而不是t,如果这是你搜索的内容。可以通过使用ENVIRON[]解决,或者通过ARGV[]访问。

*PS 如果你喜欢用三个竖条作为分隔符|||,它不能被转义,所以使用-F"[|][|][|]"

从程序/函数栈获取数据的例子,以awk为例(这里使用日期)。

awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'

代码块后的变量

这里我们在 "awk "代码后得到变量。只要你在 "BEGIN "块中不需要这个变量,这就可以正常工作。

variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file

这也适用于多个变量 awk '{print a,b,$0}' a="$var1" b="$var2" file

这样使用变量在BEGIN块中不起作用。

echo "input data" | awk 'BEGIN {print var}' var="${variable}"

Here-string

也可以使用支持[here-string][1]的shell(包括Bash)向awk添加变量。


awk '{print $0}' 
评论(6)

根据你希望如何处理shell变量中的反斜线,使用其中之一(avar是一个awk变量,svar是一个shell变量)。

awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file

详情和其他选项见http://cfajohnson.com/shell/cus-faq-2.html#Q24。上面的第一种方法几乎是你最好的选择,而且有最明显的语义。

评论(0)

你可以在命令行选项 -v中传递一个变量名(v)和一个环境变量的值(=)("${v}")。

% awk -vv="${v}" 'BEGIN { print v }'
123test

或者说得更清楚一些(用更少的 "v")。

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
评论(0)