bash 如何在 awk 脚本中使用 shell 变量?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19075671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use shell variables in an awk script?
提问by hqjma
I found some ways to pass external shell variables to an awk
script, but I'm confused about '
and "
.
我找到了一些将外部 shell 变量传递给awk
脚本的方法,但我对'
和感到困惑"
。
First, I tried with a shell script:
首先,我尝试使用 shell 脚本:
$ v=123test
$ echo $v
123test
$ echo "$v"
123test
Then tried awk:
然后尝试awk:
$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123
Why is the difference?
为什么有区别?
Lastly I tried this:
最后我试过这个:
$ 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
I'm confused about this.
我对此感到困惑。
回答by Jotne
Getting shell variables into
awk
may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below.????????????????????????????????????????????????????????????????????????????????????v1.5
获取shell变量
awk
可以通过多种方式完成。有些比其他的要好。这应该涵盖其中的大部分。如果您有意见,请在下方留言。?????????????????????????????????????????? ????????????????????????????????????????????????v1.5
Using -v
(The best way, most portable)
使用-v
(最好的方式,最便携)
Use the -v
option: (P.S. use a space after -v
or it will be less portable. E.g., awk -v var=
not awk -vvar=
)
使用-v
选项:(PS 在后面使用一个空格,-v
否则便携性会降低。例如,awk -v var=
不是awk -vvar=
)
variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two
This should be compatible with most awk
, and the variable is available in the BEGIN
block as well:
这应该与 most 兼容awk
,并且该变量也在BEGIN
块中可用:
If you have multiple variables:
如果您有多个变量:
awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'
Warning. As Ed Morton writes, escape sequences will be interpreted so \t
becomes a real tab
and not \t
if that is what you search for. Can be solved by using ENVIRON[]
or access it via ARGV[]
警告。正如 Ed Morton 所写,转义序列将被解释\t
为真实的tab
,\t
如果那是您搜索的内容,则不会。可以通过使用ENVIRON[]
或访问它来解决ARGV[]
PSIf you like three vertical bar as separator |||
, it can't be escaped, so use -F"[|][|][|]"
PS如果你喜欢三个竖线作为分隔符|||
,它不能被转义,所以使用-F"[|][|][|]"
Example on getting data from a program/function inn to
awk
(here date is used)
从程序/函数客栈获取数据的示例
awk
(此处使用日期)
awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'
Variable after code block
代码块后的变量
Here we get the variable after the awk
code. This will work fine as long as you do not need the variable in the BEGIN
block:
这里我们得到awk
代码后面的变量。只要您不需要BEGIN
块中的变量,这将正常工作:
variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file
- Adding multiple variables:
- 添加多个变量:
awk '{print a,b,$0}' a="$var1" b="$var2" file
awk '{print a,b,$0}' a="$var1" b="$var2" file
- In this way we can also set different Field Separator
FS
for each file.
- 这样我们也可以
FS
为每个文件设置不同的字段分隔符。
awk 'some code' FS=',' file1.txt FS=';' file2.ext
awk 'some code' FS=',' file1.txt FS=';' file2.ext
- Variable after the code block will not work for the
BEGIN
block:
- 代码块之后的变量将不适用于该
BEGIN
块:
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
echo "input data" | awk 'BEGIN {print var}' var="${variable}"
Here-string
这里字符串
Variable can also be added to awk
using a here-stringfrom shells that support them (including Bash):
还可以添加变量以awk
使用支持它们的 shell(包括 Bash)中的here-string:
awk '{print printf '%s' "$variable" | awk '{print X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
}'
}' <<< "$variable"
test
This is the same as:
这与:
v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data
P.S. this treats the variable as a file input.
PS 这将变量视为文件输入。
ENVIRON
input
ENVIRON
输入
As TrueY writes, you can use the ENVIRON
to print Environment Variables.
Setting a variable before running AWK, you can print it out like this:
正如 TrueY 所写,您可以使用ENVIRON
来打印Environment Variables。在运行 AWK 之前设置一个变量,你可以像这样打印出来:
v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
}' "$v"
my data test
ARGV
input
ARGV
输入
As Steven Penny writes, you can use ARGV
to get the data into awk:
正如 Steven Penny 所写,您可以使用ARGV
将数据导入 awk:
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
To get the data into the code itself, not just the BEGIN:
要将数据放入代码本身,而不仅仅是 BEGIN:
var="Line one
This is line two"
echo $var
Line one This is line two
echo "$var"
Line one
This is line two
Variable within the code: USE WITH CAUTION
代码中的变量:谨慎使用
You can use a variable within the awk
code, but it's messy and hard to read, and as Charles Duffy
points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk
code.
您可以在awk
代码中使用变量,但它很混乱且难以阅读,而且正如Charles Duffy
指出的那样,这个版本也可能是代码注入的受害者。如果有人向变量中添加了不好的东西,它将作为awk
代码的一部分执行。
This works by extracting the variable within the code, so it becomes a part of it.
这是通过提取代码中的变量来工作的,因此它成为它的一部分。
If you want to make an awk
that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.
如果您想awk
使用变量动态更改,您可以这样做,但不要将它用于普通变量。
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
Here is an example of code injection:
下面是一个代码注入的例子:
awk -v var='$variable' 'BEGIN {print var}'
$variable
You can add lots of commands to awk
this way. Even make it crash with non valid commands.
您可以通过awk
这种方式添加大量命令。甚至使用无效命令使其崩溃。
Extra info:
额外信息:
Use of double quote
双引号的使用
It's always good to double quote variable "$variable"
If not, multiple lines will be added as a long single line.
双引号变量总是好的"$variable"
如果不是,多行将作为一个长单行添加。
Example:
例子:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
Other errors you can get without double quote:
没有双引号可以得到的其他错误:
awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file
And with single quote, it does not expand the value of the variable:
并且使用单引号,它不会扩展变量的值:
% awk -vv="${v}" 'BEGIN { print v }'
123test
More info about AWK and variables
有关 AWK 和变量的更多信息
回答by TrueY
回答by Ed Morton
Use either of these depending how you want backslashes in the shell variables handled (avar
is an awk variable, svar
is a shell variable):
根据您希望如何处理 shell 变量中的反斜杠(avar
是一个 awk 变量,svar
是一个 shell 变量),使用其中的任何一个:
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
See http://cfajohnson.com/shell/cus-faq-2.html#Q24for details and other options. The first method above is almost always your best option and has the most obvious semantics.
有关详细信息和其他选项,请参阅http://cfajohnson.com/shell/cus-faq-2.html#Q24。上面的第一种方法几乎总是您的最佳选择,并且具有最明显的语义。
回答by Johnsyweb
You could pass in the command-line option-v
with a variable name (v
) and a value (=
) of the environment variable ("${v}"
):
您可以使用变量名 ( ) 和环境变量 ( )的值 ( )传入命令行选项:-v
v
=
"${v}"
awk 'BEGIN {ARGC--} {print ARGV[2], for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " }'; done
}' file "$v"
Or to make it clearer (with far fewer v
s):
或者让它更清楚(用更少的v
s):
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", ##代码##; }' /path_to_log_file/log_file.log
回答by Steven Penny
You can utilize ARGV:
您可以使用 ARGV:
##代码##Note that if you are going to continue into the body, you will need to adjust ARGC:
请注意,如果您要继续进入正文,则需要调整 ARGC:
##代码##回答by edib
I just changed @Jotne's answer for "for loop".
我刚刚更改了@Jotne 对“for 循环”的回答。
##代码##回答by Sina
I had to insert date at the beginning of the lines of a log file and it's done like below:
我必须在日志文件行的开头插入日期,它的完成方式如下:
##代码##It can be redirect to another file to save
它可以重定向到另一个文件进行保存