有没有办法在我当前的 shell 中设置一个变量awk
?
我想对文件进行一些处理并打印出一些数据;因为我将通读整个文件,所以我想保存行数——在这种情况下,FNR
.
尽管我似乎无法找到一种方法来设置带有FNR
值的 shell 变量,但还是会发生;如果不是这样,我将不得不FNR
从我的输出文件中读取,以设置,比如说num_lines
,具有FNR
值。
我尝试了一些使用 的组合awk 'END{system(...)}'
,但无法使其正常工作。有什么办法吗?
这是另一种方式。
当您将变量的值放在一个变量中并且想要将它们拆分时,这尤其有用。例如,您有一个来自数据库中单行的值列表,您希望从中创建变量。
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
我们需要“这里的字符串”,即 <<< 在这种情况下,因为读取命令不是从管道读取,而是从标准输入读取
$ 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 打印的任何字符串,这可能会意外地成为一件非常糟糕的事情!
您不能将变量从子 shell 导出到其父 shell。不过,您还有其他一些选择,包括:
使用 AWK 对文件进行另一次传递以计算记录,并使用命令替换来捕获结果。例如:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
获取您的计数。对尝试使用声明的任何人的警告,如几个答案所建议的那样。
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
打印出赋值语句:
MYVAR=NewValue
然后在你的 shell 脚本中,eval
你的脚本的输出awk
:
eval $(awk ....)
# then use $MYVAR
编辑:如果内部脚本打印了除分配以外的其他内容,人们建议使用declare
而不是eval
, 以减少出错的可能性。它是 bash-only,但是当 shell是bash 并且脚本有时#!/bin/bash
,它可以正确地说明这种依赖关系。
该eval $(...)
变体被广泛使用,现有程序生成的输出适合eval
但不适合declare
(lesspipe
例如);这就是理解它很重要的原因,而仅 bash 的变体“过于本地化”。
为了综合到目前为止的所有内容,我将分享我发现从使用 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
。
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 完成回显“完成”