从awk中设置当前shell中的变量

时间:2013-01-24 15:35:51

标签: bash variables awk

有没有办法在awk范围内的当前shell中设置变量?

我想对文件进行一些处理并打印出一些数据;因为我将通读整个文件,所以我想保存行数 - 在这种情况下,FNR

虽然我似乎无法找到一种方法来设置一个FNR值的shell变量;如果不是这样,我必须从输出文件中读取FNR,设置num_lines,并设置FNR值。

我使用awk 'END{system(...)}'尝试了一些组合,但无法管理它。有什么方法吗?

7 个答案:

答案 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。不过,您还有其他选择,包括:

  1. 使用AWK再次传递文件来计算记录,并使用命令替换来捕获结果。例如:

    FNR=$(awk 'END {print FNR}' filename)
    
  2. 在子shell中打印 FNR ,并在其他进程中解析输出。
  3. 如果 FNR 与行数相同,您可以致电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但不适合declarelesspipe就是一个例子);这就是理解它的重要性,而且仅限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 完成 回声“完成”