有没有办法在awk
范围内的当前shell中设置变量?
我想对文件进行一些处理并打印出一些数据;因为我将通读整个文件,所以我想保存行数 - 在这种情况下,FNR
。
虽然我似乎无法找到一种方法来设置一个FNR
值的shell变量;如果不是这样,我必须从输出文件中读取FNR
,设置num_lines
,并设置FNR
值。
我使用awk 'END{system(...)}'
尝试了一些组合,但无法管理它。有什么方法吗?
答案 0 :(得分:24)
$ echo "$var"
$ declare $( awk 'BEGIN{print "var=17"}' )
$ echo "$var"
17
这就是为什么你应该使用declare而不是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打印,这可能会非常糟糕!
答案 1 :(得分:21)
这是另一种方式。
当您在单个变量中获得变量的值并且您希望将它们拆分时,这尤其有用。例如,您有一个数据库中的单个行的值列表,您希望从中创建变量。
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
我们需要&#39; here string&#39;即&lt;&lt;&lt;在这种情况下,因为read命令不从管道读取而是从stdin读取
答案 2 :(得分:4)
您无法将变量从子shell导出到其父shell。不过,您还有其他选择,包括:
使用AWK再次传递文件来计算记录,并使用命令替换来捕获结果。例如:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
进行统计。答案 3 :(得分:3)
对于任何试图使用的人发出的警告都是按照几个答案建议的。
eval没有这个问题。
如果提供的awk(或其他表达式)声明结果为空字符串,则声明将转储当前环境。 这几乎肯定不是你想要的。
例如:如果输入中不存在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.
答案 4 :(得分:1)
让awk
打印出赋值语句:
MYVAR=NewValue
然后在您的shell脚本中,eval
awk
脚本的输出:
eval $(awk ....)
# then use $MYVAR
编辑:人们建议使用declare
而不是eval
,如果内部脚本打印了除分配之外的其他内容,则容易出错。它只是bash,但是当shell 是 bash并且脚本有#!/bin/bash
时,它是正常的,正确地说明了这种依赖。
eval $(...)
变体被广泛使用,现有程序生成的输出适合eval
但不适合declare
(lesspipe
就是一个例子);这就是理解它的重要性,而且仅限bash的变体“过于本地化”。
答案 5 :(得分:1)
到目前为止,为了综合所有内容,我将分享我发现从使用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
的安全风险,这将避免大量输出变量。
答案 6 :(得分:0)
echo“第一个参数:$ 1” 为((i = 0; i <$ 1; i ++));做 回声“里面” 回声“欢迎$ i次”。 猫man.xml | awk'{x [NR] = $ 0} END {for(i = 2; i <= NR; i ++){if(x [i]〜//){x [i + 1] =“'$ i'” }打印x [i]}}'> $ i.xml 完成 回声“完成”