bash 从 awk 在当前 shell 中设置变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14505026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set variable in current shell from awk
提问by Rubens
Is there a way to set a variable in my current shell from within awk
?
有没有办法在我当前的 shell 中从内部设置变量awk
?
I'd like to do some processing on a file and print out some data; since I'll read the whole file through, I'd like to save the number of lines -- in this case, FNR
.
我想对文件进行一些处理并打印出一些数据;因为我会通读整个文件,所以我想保存行数 - 在这种情况下,FNR
.
Happens though I can't seem to find a way to set a shell variable with FNR
value; if not this, I'd have to read the FNR
from my output file, to set, say num_lines
, with FNR
value.
虽然我似乎找不到一种方法来设置带有FNR
值的 shell 变量,但发生了这种情况;如果没有这一点,我不得不阅读FNR
从我的输出文件,以一套,说num_lines
,与FNR
价值。
I've tried some combinations using awk 'END{system(...)}'
, but could not manage it to work. Any way around this?
我尝试了一些使用 的组合awk 'END{system(...)}'
,但无法使其正常工作。有什么办法解决这个问题吗?
回答by Nerrve
Here's another way.
这是另一种方式。
This is especially useful when when you've got the valuesof your variables in a singlevariable and you want split them up. For example, you have a list of values from a single row in a database that you want to create variables out of.
当您将变量的值放在单个变量中并希望将它们拆分时,这尤其有用。例如,您有一个数据库中单行的值列表,您想从中创建变量。
val="hello|beautiful|world" # assume this string comes from a database query
read a b c <<< $( echo ${val} | awk -F"|" '{print " "" "}' )
echo $a #hello
echo $b #beautiful
echo $c #world
We need the 'here string' i.e <<< in this case, because the read command does not read from a pipe and instead reads from stdin
在这种情况下,我们需要“此处字符串”,即 <<<,因为读取命令不是从管道读取而是从标准输入读取
回答by Ed Morton
$ echo "$var"
$ declare $( awk 'BEGIN{print "var=17"}' )
$ echo "$var"
17
Here's why you should use declare instead of eval:
这就是为什么你应该使用声明而不是 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
Note in the first case that eval executes whatever string awk prints, which could accidentally be a very bad thing!
请注意,在第一种情况下, eval 执行 awk 打印的任何字符串,这可能是一件非常糟糕的事情!
回答by Todd A. Jacobs
You can't export variables from a subshell to its parent shell. You have some other choices, though, including:
您不能将变量从子 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)
- Print FNRin the subshell, and parse the output in your other process.
- If FNRis the same as number of lines, you can call
wc -l < filename
to get your count.
使用 AWK 对文件进行另一次传递以计算记录,并使用命令替换来捕获结果。例如:
FNR=$(awk 'END {print FNR}' filename)
- 在子 shell 中打印FNR,并在其他进程中解析输出。
- 如果FNR与行数相同,您可以致电
wc -l < filename
获取您的计数。
回答by sbts
A warning for anyone trying to use declare as suggested by several answers.
根据几个答案的建议,对任何尝试使用声明的人发出警告。
eval does not have this problem.
eval 没有这个问题。
If the awk (or other expression) provided to declare results in an empty string then declare will dump the current environment. This is almost certainly not what you would want.
如果提供用于声明的 awk(或其他表达式)结果为空字符串,则声明将转储当前环境。这几乎肯定不是您想要的。
eg: if your awk pattern doesn't exist in the input you will never print an output, therefore you will end up with unexpected behaviour.
例如:如果输入中不存在 awk 模式,则永远不会打印输出,因此最终会出现意外行为。
An example of this....
这方面的一个例子......
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
A minor change to store the value to set in an awk variable and print it at the end solves this....
将要设置的值存储在 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.
To show this working with a matching pattern
使用匹配模式显示此操作
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.
回答by Merlin
To synthesize everything here so far I'll share what I find is useful to set a shell environment variable from a script that reads a one-line file using awk. Obviously a /pattern/
could be used instead of NR==1
to find the needed variable.
到目前为止,为了综合这里的所有内容,我将分享我发现从使用 awk 读取单行文件的脚本设置 shell 环境变量有用的内容。显然/pattern/
,可以使用 a 代替NR==1
查找所需的变量。
# export a variable from a script (such as in a .dotfile)
declare $( awk 'NR==1 {tmp=} END {print "SHELL_VAR=" tmp}' /path/to/file )
export SHELL_VAR
This will avoid a massive output of variables if a declare
command is issued with no argument, as well as the security risks of a blind eval
.
这将避免在declare
没有参数的情况下发出命令时大量输出变量,以及盲人的安全风险eval
。
回答by Anton Kovalenko
Make awk
print out the assignment statement:
使awk
打印出来的赋值语句:
MYVAR=NewValue
Then in your shell script, eval
the output of your awk
script:
然后在你的 shell 脚本中,eval
你的awk
脚本的输出:
eval $(awk ....)
# then use $MYVAR
EDIT: people recommend using declare
instead of eval
, to be slightly less error-prone if something other than the assignment is printed by the inner script. It's bash-only, but it's okay when the shell isbash and the script has #!/bin/bash
, correctly stating this dependency.
编辑:如果内部脚本打印了分配以外的其他内容,人们建议使用declare
代替eval
, 以减少出错的可能性。它是 bash-only,但是当 shell是bash 并且脚本有 时#!/bin/bash
,正确地说明这种依赖关系是可以的。
The eval $(...)
variant is widely used, with existing programs generating output suitable for eval
but not for declare
(lesspipe
is an example); that's why it's important to understand it, and the bash-only variant is "too localized".
该eval $(...)
变体被广泛使用,现有程序生成的输出适合eval
但不适合declare
(lesspipe
是一个例子);这就是为什么理解它很重要,而 bash-only 变体“过于本地化”。
回答by Hari Prassana
echo "First arg: $1" for ((i=0 ; i < $1 ; i++)); do echo "inside" echo "Welcome $i times." 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 "compleated"
echo "第一个参数: $1" for ((i=0 ; i < $1 ; i++)); do echo "inside" echo "Welcome $i times." 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 "completed"