如何在 awk 脚本中使用 shell 变量? [英] How do I use shell variables in an awk script?

查看:51
本文介绍了如何在 awk 脚本中使用 shell 变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找到了一些将外部 shell 变量传递给 awk 脚本的方法,但我对 '" 感到困惑.>

首先,我尝试使用 shell 脚本:

$ v=123test$回声 $v123测试$回声$v"123测试

然后尝试了awk:

$ awk 'BEGIN{print "'$v'"}'$ 123测试$ awk 'BEGIN{print '"$v"'}'123 美元

为什么会有不同?

最后我试过这个:

$ awk 'BEGIN{print " '$v' "}'$ 123测试$ awk 'BEGIN{print ' "$v" '}'awk:cmd.第 1 行:开始{打印awk:cmd.line:1: ^ 意外的换行符或字符串结尾

我对此感到困惑.

解决方案

#Getting shell variables into awk可以通过多种方式完成.有些比其他的要好.这应该涵盖其中的大部分.如果您有意见,请在下方留言.v1.5


使用-v(最好的方法,最便携)

使用 -v 选项:(PS 在 -v 后使用一个空格,否则会降低可移植性.例如,awk -v var= 不是 awk -vvar=)

variable=第一行
第二行"awk -v var="$变量";'开始{打印变量}'第一行第二行

这应该与大多数 awk 兼容,并且该变量也可以在 BEGIN 块中使用:

如果你有多个变量:

awk -v a=$var1";-v b=$var2"'开始{打印a,b}'

警告.正如 Ed Morton 所写,转义序列将被解释为 成为一个真正的 tab 而不是 如果这是您搜索的内容.可以使用ENVIRON[]解决或者通过ARGV[]

访问

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

<块引用>

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

awk -v time=$(date +"%F %H:%M" -d '-1 分钟')";'开始{打印时间}'

<块引用>

将 shell 变量的内容测试为正则表达式的示例:

awk -v var="$variable";'$0 ~ var{print 找到它"}'


代码块后的变量

这里我们得到了 awk 代码之后的变量.只要您不需要 BEGIN 块中的变量,这将正常工作:

variable=第一行
第二行"回声输入数据"|awk '{print var}' var="${variable}";或者awk '{print var}' var="${variable}";文件

  • 添加多个变量:

awk '{print a,b,$0}' a=$var1";b=$var2"文件

  • 这样我们也可以为每个文件设置不同的字段分隔符FS.

awk 'some code' FS=',' file1.txt FS=';'file2.ext

  • 代码块之后的变量对 BEGIN 块不起作用:

回显输入数据"|awk 'BEGIN {print var}' var="${variable}"


此处字符串

也可以使用here-stringawka> 来自支持它们的 shell(包括 Bash):

awk '{print $0}' <<<$变量"测试

这与:

printf '%s' "$variable";|awk '{print $0}'

附言这将变量视为文件输入.


ENVIRON 输入

正如 TrueY 所写,您可以使用 ENVIRON 打印环境变量.在运行AWK之前设置一个变量,可以这样打印出来:

X=MyVarawk 'BEGIN{print ENVIRON[X"],ENVIRON[SHELL"]}'MyVar/bin/bash


ARGV 输入

正如 Steven Penny 所写,您可以使用 ARGV 将数据导入 awk:

v=我的数据"awk 'BEGIN {print ARGV[1]}' "$v";我的数据

要将数据放入代码本身,而不仅仅是 BEGIN:

v=我的数据"回声测试"|awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v";我的数据测试


代码中的变量:谨慎使用

您可以在 awk 代码中使用变量,但它很混乱且难以阅读,而且正如 Charles Duffy 指出的那样,这个版本也可能是代码注入.如果有人向变量中添加了不好的东西,它将作为 awk 代码的一部分执行.

这是通过提取代码中的变量来工作的,因此它成为它的一部分.

如果你想制作一个使用变量动态变化的awk,你可以这样做,但不要将它用于普通变量.

variable=第一行
第二行"awk 'BEGIN {print "'"$variable"'"}'第一行第二行

这是代码注入的示例:

variable='第一行
第二行";for (i=1;i<=1000;++i) 打印 i"'awk 'BEGIN {print "'"$variable"'"}'第一行第二行123..1000

您可以通过这种方式向 awk 添加大量命令.甚至使用无效命令使其崩溃.

不过,这种方法的一个有效用途是当您想将符号传递给 awk 以应用于某些输入时,例如一个简单的计算器:

$ calc() { awk -v x=$1";-v z=$3"'BEGIN{ 打印 x ''$2'''z }';}$ 计算 2.7 '+' 3.46.1$ 计算 2.7 '*' 3.49.18

使用填充有 shell 变量值的 awk 变量无法做到这一点,您需要在 awk 解释它之前将 shell 变量扩展为 awk 脚本文本的一部分.


额外信息:

双引号的使用

双引号变量总是好的"$variable"
如果不是,多行将添加为一个长单行.

示例:

var="第一行这是第二行"回声 $var第一行 这是第二行echo "$var";一号线这是第二行

没有双引号的其他错误:

variable=第一行
第二行"awk -v var=$variable 'BEGIN {print var}'awk:cmd.行:1: 一个
行awk:cmd.行:1:^ 反斜杠不是行中的最后一个字符awk:cmd.行:1: 一个
行awk:cmd.第 1 行:^ 语法错误

并且使用单引号,它不会扩展变量的值:

awk -v var='$variable' 'BEGIN {print var}'$变量

有关 AWK 和变量的更多信息

阅读此常见问题解答.

I found some ways to pass external shell variables to an awk script, but I'm confused about ' and ".

First, I tried with a shell script:

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

Then tried 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.

解决方案

#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


Using -v (The best way, most portable)

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=)

variable="line one
line 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:

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 becomes a real tab and not if that is what you search for. Can be solved by using ENVIRON[] or access it via ARGV[]

PS If you like three vertical bar as separator |||, it can't be escaped, so use -F"[|][|][|]"

Example on getting data from a program/function inn to awk (here date is used)

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

Example of testing the contents of a shell variable as a regexp:

awk -v var="$variable" '$0 ~ var{print "found it"}'


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:

variable="line one
line 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

  • In this way we can also set different Field Separator FS for each file.

awk 'some code' FS=',' file1.txt FS=';' file2.ext

  • Variable after the code block will not work for the BEGIN block:

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


Here-string

Variable can also be added to awk using a here-string from shells that support them (including Bash):

awk '{print $0}' <<< "$variable"
test

This is the same as:

printf '%s' "$variable" | awk '{print $0}'

P.S. this treats the variable as a file input.


ENVIRON input

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:

X=MyVar
awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash


ARGV input

As Steven Penny writes, you can use ARGV to get the data into awk:

v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data

To get the data into the code itself, not just the BEGIN:

v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test


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.

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.

variable="line one
line two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two

Here is an example of code injection:

variable='line one
line two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000

You can add lots of commands to awk this way. Even make it crash with non valid commands.

One valid use of this approach, though, is when you want to pass a symbol to awk to be applied to some input, e.g. a simple calculator:

$ calc() { awk -v x="$1" -v z="$3" 'BEGIN{ print x '"$2"' z }'; }

$ calc 2.7 '+' 3.4
6.1

$ calc 2.7 '*' 3.4
9.18

There is no way to do that using an awk variable populated with the value of a shell variable, you NEED the shell variable to expand to become part of the text of the awk script before awk interprets it.


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.

Example:

var="Line one
This is line two"

echo $var
Line one This is line two

echo "$var"
Line one
This is line two

Other errors you can get without double quote:

variable="line one
line two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one
line
awk: cmd. line:1:    ^ backslash not last character on line
awk: cmd. line:1: one
line
awk: cmd. line:1:    ^ syntax error

And with single quote, it does not expand the value of the variable:

awk -v var='$variable' 'BEGIN {print var}'
$variable

More info about AWK and variables

Read this faq.

这篇关于如何在 awk 脚本中使用 shell 变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆