有没有办法通过 awk
在当前 shell 中设置一个变量?
我想在处理文件并打印一些数据时保存行数 - 在这种情况下,保存 FNR
的数量。
但是,我似乎找不到一种使用 FNR
值设置 shell 变量的方法;如果不能实现这个,我将不得不从输出文件中读取 FNR
来设置 num_lines
变量的值。
我已经尝试了一些组合,例如 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
在这种情况下,我们需要使用“here string”,即 <<<,因为read命令无法从管道中读取,而是从stdin中读取
$ 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打印的任何字符串,这可能会意外地造成非常糟糕的后果!
eval
并不会有太大问题。 - Rubens你无法从子shell导出变量到父shell。不过你还有其他选择,包括:
Make another pass of the file using AWK to count records, and use command substitution to capture the result. For example:
FNR=$(awk 'END {print FNR}' filename)
wc -l < filename
to get your count.FNR=$(awk 'END {print FNR}' filename)
和 FNR=$(wc -l filename | awk '{print $1}')
相当相似,除了一个程序计算行数 -- awk
/wc
。 - Rubenswc -l <文件名>
就可以了。 - Ed Morton警告:如果您尝试使用一些答案中建议的declare,请注意。
eval没有这个问题。
如果提供给declare的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.
declare "$( ... )"
。 - Gerard van Helden/pattern/
代替NR==1
来找到所需的变量。请注意保留html标签。# 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
的安全风险。
让 awk
输出赋值语句:
MYVAR=NewValue
然后在您的Shell脚本中,eval
您的awk
脚本的输出:
eval $(awk ....)
# then use $MYVAR
编辑:人们建议使用declare
而不是eval
,如果内部脚本打印除赋值以外的内容,这样可以稍微减少一些错误。它仅适用于bash,但当shell是bash且脚本具有#!/bin/bash
时,正确说明此依赖关系就可以了。
eval $(...)
变体被广泛使用,现有程序生成适用于eval
但不适用于declare
的输出(例如lesspipe
);因此,理解它非常重要,而仅适用于bash的变体则“太局限”了。
declare
而不是 eval
。 - chepnerdeclare
是仅限于 Bash 的,这并不一定是坏事,但这就是为什么我默认不使用它的原因。 - Anton Kovalenkovar=$(awk 'END { print 17 }' </dev/null)
,其中 Awk 只提供值,而 shell 决定如何处理它。 - tripleeeecho "第一个参数: $1" for ((i=0 ; i < $1 ; i++)); do echo "内部" echo "欢迎您第 $i 次。" cat man.xml | awk '{ x[NR] = $0 } END { for ( i=2 ; i<=NR ; i++ ) { if (x[i] ~ // ) {x[i+1]=" '$i'"}print x[i] }} ' > $i.xml done echo "完成"
read a b c <<< $(echo ${val})
- Nick XIFS=',' read aa bb <<< $(echo ${line} | awk -F',' '{print $3","$4}')
如果只有空格,则按其编号仅取所需的空格。 - nrp