3

我正在编写一个 bash 脚本,该脚本循环遍历命令替换的输出,然后尝试在循环体内执行另一个命令替换。这是代码:

#!/usr/bin/bash

IFS=$'\n' 

for i in $( xmllint --xpath "string(/*[local-name()='Project'])" gsGDAL/gsGDAL.vcxproj.user )
do
   IFS=' ' #attempted with and without this line
   "$( awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i) )"
   IFS=$'\n' #attempted with and without this line
done

我将 IFS 设置为换行符,以便循环遍历 xmllint 命令的每一行输出,而不是遍历每个以空格分隔的单词。但是,这会使循环内的命令替换失败。一些调试得出结论,问题的本质是这样的:

#!/usr/bin/bash

IFS=$'\n'

$(echo export TEST="test")

这给出了错误:

./x.sh: line 6: export TEST=test: command not found

您可以看到我在第一个代码示例中尝试通过在循环中重置 IFS 来进行修复。那没有用。

我意识到我可以使用脚本的不同习语来解决问题。
例如,将 xmllint 命令替换为 awk 的过程,而不是在每个单独的行上执行 awk 来命名一种可能性。欢迎对此发表评论,但请提交与以下相关的答案:

  1. 为什么将 IFS 设置为换行符会混淆命令替换生成的导出?
  2. 为什么在循环中重置 IFS 不能解决问题?

更新:根据与 Barmar 的讨论,IFS 用于命令/变量扩展后的分词。

4

2 回答 2

4

我不认为IFS是你的问题的原因。您的代码有两个问题:

  1. 你加$(awk ...)了双引号,所以没有进行分词。因此它被视为export varname="value"命令的名称——空格是命令名称的一部分,而不是命令和参数之间的分隔符。

  2. 即使没有双引号,它也不起作用,因为对命令替换的结果不进行引号处理,只进行分词和通配符扩展。因此,命令中的双引号export将作为文字字符包含在所分配的值中。

正如 mplf 所指出的,解决方案是使用eval

eval "$(awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i) )"
于 2013-06-13T01:22:49.027 回答
2

用于eval评估从子外壳返回的字符串。

IFS=' ' #attempted with and without this line
eval $( awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i) )
IFS=$'\n' #attempted with and without this line
于 2013-06-13T00:52:11.130 回答