我找到了一些方法将外部shell变量传递给awk
脚本,但我对'
和"
感到困惑。
首先,我尝试使用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
我对此很困惑。
答案 0 :(得分:396)
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[]
这里我们得到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}"
还可以使用支持它们的shell(包括Bash)中的here-string将变量添加到awk
:
awk '{print $0}' <<< "$variable"
test
这与:
相同printf '%s' "$variable" | awk '{print $0}'
P.S。这会将变量视为文件输入。
ENVIRON
输入正如TrueY所写,您可以使用ENVIRON
打印环境变量。
在运行AWK之前设置变量,可以像这样打印出来:
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
ARGV
输入正如Steven Penny所写,您可以使用ARGV
将数据输入awk:
v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data
要将数据放入代码本身,而不仅仅是BEGIN:
v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test
您可以在awk
代码中使用变量,但它很麻烦且难以阅读,而Charles Duffy
指出,此版本也可能是代码注入的受害者。如果有人向变量添加了不好的内容,它将作为awk
代码的一部分执行。
这是通过在代码中提取变量来实现的,因此它就成了它的一部分。
如果你想使用变量动态改变awk
,你可以这样做,但不要将它用于普通变量。
variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
以下是代码注入的示例:
variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000
您可以通过这种方式向awk
添加大量命令。甚至使用无效命令使其崩溃。
双引号变量"$variable"
总是好的
如果没有,将添加多行作为长单行。
示例:
var="Line one
This is line two"
echo $var
Line one This is line two
echo "$var"
Line one
This is line two
如果没有双引号,您可以获得其他错误:
variable="line one\nline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ backslash not last character on line
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ syntax error
使用单引号,它不会扩展变量的值:
awk -v var='$variable' 'BEGIN {print var}'
$variable
答案 1 :(得分:24)
似乎根本没有提到好的ENVIRON
awk内置哈希。其用法示例:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
答案 2 :(得分:8)
根据处理的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。上面的第一种方法几乎总是你最好的选择,并且具有最明显的语义。
答案 3 :(得分:5)
您可以使用变量名称(-v
)和环境变量值v
)传递command-line option =
("${v}"
) :
% awk -vv="${v}" 'BEGIN { print v }'
123test
或者使其更清晰(v
s更少):
% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
答案 4 :(得分:3)
您可以使用ARGV:
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
请注意,如果您要继续进入身体,则需要进行调整 ARGC:
awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"
答案 5 :(得分:1)
我必须在日志文件的行的开头插入日期,并且如下所示:
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
可以重定向到另一个文件进行保存
答案 6 :(得分:0)
我刚刚改变了@ Jotne的回答#34; for循环&#34;。
for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done
答案 7 :(得分:0)
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done
答案 8 :(得分:0)
创建一个处理此问题的函数可能会派上用场,这样您就不必每次都键入所有内容。使用我们选择的解决方案...
awk_switch_columns() {
cat < /dev/stdin | awk -v a="$1" -v b="$2" " { t = \$a; \$a = \$b; \$b = t; print; } "
}
并将其用作...
echo 'a b c d' | awk_switch_columns 2 4
Output:
a d c b