首先发布在这里,但多年来一直是潜伏者。我已经谷歌搜索了很多年,但无法找到我想要的东西(许多不切实际的话题主题,不要求主题暗示它做什么......)。不是awk或脚本的新手,只是有点生锈:)
我正在尝试编写一个awk脚本,它将在运行时设置shell env值 - 以便另一个bash脚本可以在以后使用它。我不能简单地使用来自awk的stdout来报告我想要设置的值(即“export whatever = awk cmd here
”),因为那已经指向awkscript正在创建的'结果文件'(加上我有多个无论如何都要在最终代码中导出变量)。
作为示例测试脚本,演示我的问题:
echo $MYSCRIPT_RESULT # returns nothing, not currently set
echo | awk -f scriptfile.awk # do whatever, setting MYSCRIPT_RESULT as we go
echo $MYSCRIPT_RESULT # desired: returns the env value set in scriptfile.awk
在scriptfile.awk中,我尝试过(没有成功)
1 /)直接构建并执行adhoc字符串:
{
cmdline="export MYSCRIPT_RESULT=1"
cmdline
}
2 /)使用系统功能:
{
cmdline="export MYSCRIPT_RESULT=1"
system(cmdline)
}
......但这些都行不通。我怀疑这两个命令是在shell中创建一个子shell,awk正在执行,并按照我的要求进行操作(通过将文件作为测试来证明),但是一旦“cmd”/系统调用完成,子shell就会死掉,不幸的是采取我设置的任何东西 - 所以我的环境设置改变不要坚持“awk的调用者”的观点。
所以我的问题是,你如何在awk 中直接设置env变量,以便调用进程可以在awk执行完成后访问这些env值?它真的可能吗?
除了上面的adhoc /系统方式,我已经证明我失败了,我无法看到如何做到这一点(除了将这些值写入某个地方的'随机'文件以便通过调用读取和读取脚本,无论如何,imo有点脏),因此,帮助!
欢迎所有想法/建议/评论!
答案 0 :(得分:5)
您无法更改父进程的环境。如果
MYSCRIPT_RESULT=$(awk stuff)
是不可接受的,你所要求的是无法完成的。
答案 1 :(得分:2)
你可以这样做,但它有点像kludge。由于awk
不允许重定向到文件描述符,因此可以使用fifo或常规文件:
$ mkfifo fifo
$ echo MYSCRIPT_RESULT=1 | awk '{ print > "fifo" }' &
$ IFS== read var value < fifo
$ eval export $var=$value
没有必要拆分var和value;你可以很容易地用awk打印&#34; export&#34;并直接评估输出。
答案 2 :(得分:1)
您也可以使用类似于描述的内容 Set variable in current shell from awk
unset var
var=99
declare $( echo "foobar" | awk '/foo/ {tmp="17"} END {print "var="tmp}' )
echo "var=$var"
var=
awk END子句是必不可少的,否则如果模式没有匹配,则声明将当前环境转储到stdout并且不会更改变量的内容。
可以通过用空格分隔多个值来设置。
declare a=1 b=2
echo -e "a=$a\nb=$b"
注意:declare只是bash,对于其他shell,使用具有相同语法的eval。
答案 3 :(得分:0)
我找到了一个很好的答案。将所有内容封装在子外壳中! comand声明的工作方式如下:
#Creates 3 variables
declare var1=1 var2=2 var3=3
ex1:
#Exactly the same as above
$(awk 'BEGIN{var="declare "}{var=var"var1=1 var2=2 var3=3"}END{print var}')
我发现了这项技术的一些非常有趣的用途。在下一个示例中,我有几个带有标签的分区。我将标签用作变量名,将设备名称用作变量值来创建变量。
ex2:
#Partition data
lsblk -o NAME,LABEL
NAME LABEL
sda
├─sda1
├─sda2
├─sda5 System
├─sda6 Data
└─sda7 Arch
#Creates a subshell to execute the text
$(\
#Pipe lsblk to awk
lsblk -o NAME,LABEL | awk \
#Initiate the variable with the text for the declare command
'BEGIN{txt="declare "}'\
#Filters devices with labels Arch or Data
'/Data|Arch/'\
#Concatenate txt with itself plus text for the variables(name and value)
#substr eliminates the special caracters before the device name
'{txt=txt$2"="substr($1,3)" "}'\
#AWK prints the text and the subshell execute as a command
'END{print txt}'\
)
此操作的最终结果是2个变量:值为Data
的{{1}}和值为sda6
的{{1}}。
同一示例在一行中。
Arch