Bash 如何在awk脚本中使用shell变量?
我找到了一些将外部shell变量传递给Bash 如何在awk脚本中使用shell变量?,bash,shell,awk,Bash,Shell,Awk,我找到了一些将外部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 $ a
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
我对此感到困惑。您可以通过变量名(v
)和环境变量(“${v}”
)的值(=
)传入-v
:
或者更清楚地说(使用更少的v
s):
#将shell变量放入awk
可能有几种方法。有些方法比其他方法更好。这应该涵盖其中的大部分。如果您有意见,请在下面留下。v1.5
##使用
-v
(最好的方式,最便携)
使用-v
选项:(请在-v
之后使用空格,否则它的可移植性会降低。例如,awk-v var=
而不是awk-vvar=
)
这应该与大多数awk
兼容,并且变量也可在BEGIN
块中使用:
如果您有多个变量:
awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'
警告。正如Ed Morton所写,转义序列将被解释为\t
成为真正的选项卡
,而不是\t
,如果这是您搜索的内容。可以通过使用环境[]
或通过ARGV[]访问它来解决
PS如果您喜欢三个竖条作为分隔符| | | |
,它不能被转义,所以请使用-F“[|][|][|]
从程序/函数inn获取数据到awk
(此处使用日期)的示例
将shell变量的内容作为regexp进行测试的示例:
##代码块后的变量
这里我们得到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”文件
- 这样,我们还可以为每个文件设置不同的字段分隔符
FS
awk'some code'FS=','file1.txt FS=';'file2.ext
- 代码块后的变量对于
BEGIN
块不起作用:
echo“输入数据”| awk“开始{print var}”var=“${variable}”
##这里是字符串
还可以使用来自支持变量的shell(包括Bash)的命令将变量添加到awk
:
另外,这将变量视为文件输入
##环境
输入
正如TrueY所写,您可以使用环境
打印环境变量。
在运行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
要将数据输入代码本身,而不仅仅是开始:
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
不使用双引号可以得到的其他错误:
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
awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
###有关AWK和变量的更多信息
.根据您希望如何处理shell变量中的反斜杠,使用这两种方法之一(avar
是awk变量,svar
是shell变量):
有关详细信息和其他选项,请参阅。上面的第一种方法几乎总是您最好的选择,并且具有最明显的语义。似乎根本没有提到好的旧环境
内置哈希。其用法示例如下:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
我必须在日志文件行的开头插入日期,操作如下:
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
它可以重定向到另一个文件以保存您可以使用ARGV:
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
请注意,如果要继续进入身体,则需要进行调整
ARGC:
我刚刚改变了@Jotne对“for loop”的回答
专业提示
它可以方便地创建一个处理此问题的函数,这样您就不必每次都键入所有内容
awk_switch_columns() {
cat < /dev/stdin | awk -v a="$1" -v b="$2" " { t = \$a; \$a = \$b; \$b = t; print; } "
}
“凌乱且难以阅读”在直接将字符串替换到awk代码中时忽略了代码注入的更重要的安全问题。阅读上面的答案,我可以运行我的脚本而不会出错,但它不能完成以下任务:awk-v repo=“$1”-v tag=“$2”{sub(/image:registryabx.azurecr.io\/{print repo}:([a-z0-9]+)$/,“image:registryabc.azurecr.io/{print repo}:{print tag}”);}1'/services/appscompose.yaml>>newcompose.yaml.是因为嵌套的括号{?@DarionBadlydone尝试这个awk-v repo=“$1”-v tag=“$2”'开始{print”repo=“repo”,tag=“tag}“
。它将查看它是否打印变量。如果您无法理解,请发布自己的问题。@Jotne yes它打印值,因此我尝试了以下方法:awk-v repo=“$1”-v tag=“$2”{print”{sub(/image:registryabc.azurecr.io/“repo”):([a-z0-9]+)$/,\“image:registryabc.azurecr.io/“repo:”tag“\”;}1}'./services/appscompose.yaml>>newcompose.yaml,但它不作为aspected工作。它用打印的command@DarionBadlydonesed是一个比awk更糟糕的选择,因为它没有
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
awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"
for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done
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