有没有办法在awk
以内的当前shell中设置变量?在awk的当前shell中设置变量
我想对一个文件进行一些处理,并打印出一些数据;因为我会读整个文件,所以我想节省行数 - 在这种情况下,FNR
。
偏偏虽然我似乎无法找到一种方法来设置与FNR
值shell变量;如果不是这样的话,我必须从我的输出文件中读取FNR
,以设置num_lines
,其值为FNR
。
我一直在使用awk 'END{system(...)}'
尝试了一些组合,但不能管理它的工作。任何方式在这个?
有没有办法在awk
以内的当前shell中设置变量?在awk的当前shell中设置变量
我想对一个文件进行一些处理,并打印出一些数据;因为我会读整个文件,所以我想节省行数 - 在这种情况下,FNR
。
偏偏虽然我似乎无法找到一种方法来设置与FNR
值shell变量;如果不是这样的话,我必须从我的输出文件中读取FNR
,以设置num_lines
,其值为FNR
。
我一直在使用awk 'END{system(...)}'
尝试了一些组合,但不能管理它的工作。任何方式在这个?
$ echo "$var"
$ declare $(awk 'BEGIN{print "var=17"}')
$ echo "$var"
17
这也是为什么你应该使用声明的,而不是EVAL:
$ eval $(awk 'BEGIN{print "echo \"removing all of your files, ha ha ha....\""}')
removing all of your files, ha ha ha....
$ declare $(awk 'BEGIN{print "echo \"removing all of your files\""}')
bash: declare: `"removing': not a valid identifier
bash: declare: `files"': not a valid identifier
注意在EVAL执行的任何字符串AWK打印第一种情况下,这可能会意外地是一个非常糟糕的事情!
让awk
打印出来的赋值语句:
MYVAR=NewValue
然后在你的shell脚本,eval
您awk
脚本的输出:
eval $(awk ....)
# then use $MYVAR
编辑:人建议使用declare
代替eval
,如果内部脚本打印的是分配以外的内容,则稍微不太容易出错。它只是bash而已,但是当shell 为 bash且脚本具有#!/bin/bash
时,可以正确指出此依赖关系。
eval $(...)
变体被广泛使用,现有的程序产生适合eval
的输出,但不适用于declare
(lesspipe
是一个例子);这就是为什么理解它很重要的原因,而且仅限bash的变体是“太本地化”的。
您无法将变量从子shell导出到其父shell。你有一些其他的选择,不过,包括:
请使用AWK来计算记录文件的另一个通,并用命令替换来捕获结果。例如:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
,让您的计数。这是另一种方法。
时,当你有值的变量的在单变量,你想拆起来这是非常有用的。例如,您可以从数据库中的单行中获取要创建变量的值列表。
val="hello|beautiful|world" # assume this string comes from a database query
read a b c <<< $(echo ${val} | awk -F"|" '{print $1" "$2" "$3}')
echo $a #hello
echo $b #beautiful
echo $C#world
我们需要“这里串”在这种情况下,即< < <,因为读命令不会从管道中读取并从标准
这正是我所需要的!我已经有了一个由空格分隔的字符串,所以我只是在输入就像在“read abc <<< $ var”中一样。谢谢 –
<3 ..感谢。 – calbertts
有一点需要提一下,如果字段之间用空格隔开,可以简化为: ''' read abc < << $(echo $ {val}) ''' –
警告任何人试图使用声明为而不是读由几个答案建议。
eval没有这个问题。
如果提供的awk(或其他表达式)声明结果为空字符串,则declare将转储当前环境。 这几乎肯定不是你想要的。
例如:如果您的awk模式不存在于输入中,您将永远不会打印输出,因此最终会出现意外的行为。
这样的一个例子....
unset var
var=99
declare $(echo "foobar" | awk '/fail/ {print "var=17"}')
echo "var=$var"
var=99
The current environment as seen by declare is printed
and $var is not changed
一个小的改动,以存储该值在AWK变量来设置并在结束打印解决了这个....
unset var
var=99
declare $(echo "foobar" | awk '/fail/ {tmp="17"} END {print "var="tmp}')
echo "var=$var"
var=
This time $var is unset ie: set to the null string var=''
and there is no unwanted output.
要显示有匹配模式
unset var
var=99
declare $(echo "foobar" | awk '/foo/ {tmp="17"} END {print "var="tmp}')
echo "var=$var"
var=
This time $var is unset ie: set to the null string var=''
and there is no unwanted output.
要合成这里的一切这方面的工作,到目前为止,我会分享我觉得是非常有用的从使用awk读取单行文件的脚本设置shell环境变量。显然/pattern/
可以用来代替NR==1
找到需要的变量。
# export a variable from a script (such as in a .dotfile)
declare $(awk 'NR==1 {tmp=$1} END {print "SHELL_VAR=" tmp}' /path/to/file)
export SHELL_VAR
这将避免变量的大量输出,如果declare
命令不带参数,还有的盲eval
的安全风险发出。
+1,但只要是我编写代码,使用'eval'我就没有多大的问题了。 – Rubens
@Rubens,直到你意外地做坏事的那一天。如果您现在习惯于编写安全代码,您将来不会被咬。 –
@glennjackman +1感谢您的提示;我想这就是为什么在这里考虑安全编码的原因(: – Rubens