23

有没有办法在我当前的 shell 中设置一个变量awk

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

尽管我似乎无法找到一种方法来设置带有FNR值的 shell 变量,但还是会发生;如果不是这样,我将不得不FNR从我的输出文件中读取,以设置,比如说num_lines,具有FNR值。

我尝试了一些使用 的组合awk 'END{system(...)}',但无法使其正常工作。有什么办法吗?

4

7 回答 7

33

这是另一种方式。

当您将变量的放在一个变量中并且想要将它们拆分时,这尤其有用。例如,您有一个来自数据库中单行的值列表,您希望从中创建变量。

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

我们需要“这里的字符串”,即 <<< 在这种情况下,因为读取命令不是从管道读取,而是从标准输入读取

于 2014-12-17T09:17:32.590 回答
31
$ 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 打印的任何字符串,这可能会意外地成为一件非常糟糕的事情!

于 2013-01-24T16:09:59.900 回答
6

您不能将变量从子 shell 导出到其父 shell。不过,您还有其他一些选择,包括:

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

    FNR=$(awk 'END {print FNR}' filename)
    
  2. 在 subshel​​l 中打印FNR,并在其他进程中解析输出。
  3. 如果FNR与行数相同,您可以致电wc -l < filename获取您的计数。
于 2013-01-24T15:41:42.863 回答
3

对尝试使用声明的任何人的警告,如几个答案所建议的那样。

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.
于 2015-11-17T11:50:22.620 回答
1

awk打印出赋值语句:

MYVAR=NewValue

然后在你的 shell 脚本中,eval你的脚本的输出awk

eval $(awk ....)
# then use $MYVAR

编辑:如果内部脚本打印了除分配以外的其他内容,人们建议使用declare而不是eval, 以减少出错的可能性。它是 bash-only,但是当 shellbash 并且脚本有时#!/bin/bash,它可以正确地说明这种依赖关系。

eval $(...)变体被广泛使用,现有程序生成的输出适合eval但不适合declarelesspipe例如);这就是理解它很重要的原因,而仅 bash 的变体“过于本地化”。

于 2013-01-24T15:38:23.097 回答
1

为了综合到目前为止的所有内容,我将分享我发现从使用 awk 读取单行文件的脚本中设置 shell 环境变量有用的内容。显然/pattern/可以使用 a 而不是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

于 2016-05-25T00:43:58.983 回答
-1

echo "First arg: $1" for ((i=0 ; i < $1 ; i++)); do echo "inside" echo "Welcome $i times." 猫人.xml | awk '{ x[NR] = $0 } END { for ( i=2 ; i<=NR ; i++ ) { if (x[i] ~ // ) {x[i+1]=" '$i'" }print x[i] }} ' > $i.xml 完成回显“完成”

于 2018-10-30T11:30:56.390 回答