我有这个脚本,旨在将变量分配给命令,这些命令收集有关系统的信息,然后将其回显。这对于前几个命令非常有效,但是最后一个命令继续返回值,而不会从输出中删除“ PRETTY_NAME =“。
我没有看到这个问题吗?
我尝试使用grep分隔awk:
grep PRETTY_NAME /etc/*-release | awk -F '=' '{print $2}'
使用转义引号:
awk -F \"=\" '/PRETTY_NAME/ {print $2}' /etc/*-release
整块(相关性进行了一些编辑)
declare -A CMDS=(
[primaryMacAddress]="cat /sys/class/net/$(ip route show default | awk '/default/ {print $5}')/address"
[primaryIpAddress]="hostname --ip-address"
[hostname]="hostname"
[osType]="awk -F '=' '/PRETTY_NAME/ {print $2}' /etc/*-release"
)
#This bit is actually nested in another function
for kpair in "${!CMDS[@]}" do
echo "$kpair=\"$( eval ${CMDS[$kpair]} )\""
done
从.sh文件运行时的结果:
osType =“ PRETTY_NAME =” Red Hat Enterprise Linux Server 7.4(Maipo)“”
预期:
osType =“”红帽企业版Linux服务器7.4(Maipo)“”
单独运行此命令时,它似乎可以正常运行:
$ awk -F'=''/ PRETTY_NAME / {print $ 2}'/ etc / *-release
“ Red Hat Enterprise Linux Server 7.4(Maipo)”
答案 0 :(得分:1)
由于您的Awk命令用双引号指定,因此内部美元符号会受到特殊处理:$2
被shell视为参数替换,因此array元素不存储文本{ {1}},而是它的扩展。 Awk解释器永远不会看到$2
语法。
但是,命令调度程序中还有第二个问题。您的$2
命令不会阻止单词拆分:
eval
您想要这个:
eval ${CMDS[$kpair]}
不带引号,您的命令被任意切成空白。然后eval "${CMDS[$kpair]}"
将片段连接在一起,并在它们之间使用一个空格,并评估结果语法。可以通过以下示例来证明差异:
eval
我们可以使用$ cmd="awk '/foo/ { print \$1\" \"\$2 }'"
$ echo 'foo a' | eval $cmd
foo a
$ echo 'foo a' | eval "$cmd"
foo a
来了解问题:
echo
$ echo $cmd
awk '/foo/ { print $1" "$2 }'
$ echo "$cmd"
awk '/foo/ { print $1" "$2 }'
的替换和随后的单词拆分均与cmd包含的任何shell语法无关。我们可以看到这样的片段:
$cmd
当我们执行$ for x in $cmd ; do echo "<$x>" ; done
<awk>
<'/foo/>
<{>
<print>
<$1">
<"$2>
<}'>
时,上面的片段将由eval $cmd
生成并重新组合并进行评估。不用说,您不希望这样分割命令语法并将其重新组合;谁知道会出现什么样的隐藏错误。您现在拥有的命令可能还可以,但是作为一种通用的命令分配机制,它存在缺陷。