【问题标题】:xargs -I replace-str in find ... -exec sedxargs -I replace-str in find ... -exec sed
【发布时间】:2019-04-09 09:29:30
【问题描述】:

我在使用 Bash 4.4.23 的 GNU/Linux 系统上,并且我有一个包含一些 Bash 变量的文件:

例如

export VARONE="var1"
export VARTWO="var2"
...

我必须将“templates”文件夹下其他扩展名为“.template”的文件中的${VARIABLE}替换为{{VARIABLE}}

我尝试执行这个命令:

cat varfile \
  | grep export \
  | awk -F '=' '{print $1}' \
  | awk '{print $2}' \
  | xargs -I var -- \
      find templates -type f -iname "*.template" \
        -exec sed 's/${var}/{{var}}/g' {} \;

但我没有运气 :( sed 似乎与这个 LHS 不匹配,实际上它将原始文件打印为输出。

谁能解释一下上面的命令有什么问题?

【问题讨论】:

  • 您需要 -i 选项到 sed 以使其更新文件到位。否则它只会在标准输出上打印结果。
  • 顺便说一句,如果您以竖线字符 (|) 结束一行,则无需转义换行符,仍然可以缩进下一个命令。您可以将grep export varfile 作为第一行并且不需要cat。如果您使用方括号,您可以列出多个字符作为awk 的分隔符,并且可以合并您的两个awk 命令。这些都回答您的问题;这只是你可能想要调整以方便阅读和性能的观察,尽管我怀疑性能确实会杀死你。 :)
  • @PaulHodges 感谢您的建议,StackOverflow 已自动添加换行符转义,可能是因为我已将所有命令写在一行中。我不知道 awk 的多个分隔符选项,我真的很感激。
  • @Barmar 是的,你是对的,我已经意识到缺少 -i 来测试命令导致我出错,我的命令在将替换写入时实际上可以很好地工作文件,非常感谢。
  • @PaulHodges 逃脱来自 ruakh 的编辑。

标签: bash sed find xargs


【解决方案1】:

唯一的问题似乎是缺少-i 标志和未转义的$ 用于sed。

这是一个经过上述修复的更简单、经过测试的初始管道:

sed -nE '/^export /{s///;s/([^=]+).*/\1/;p;}' varfile |
    xargs -I var -- find templates -name '*.template' -exec sed -i '' 's/\${var}/{{var}}/g' {} +

为了保证,如果变量每行出现多次,我添加了g 标志。

【讨论】:

  • 为什么是s///;
  • 似乎不需要 $ char 的转义,因为在单个顶点之间包含的字符串中,bash 不会进行替换,而 xargs 会正确替换“var”。感谢您对我的代码的改进。
  • 事实上,这可能适用于大多数 sed 实现(也许全部?)。这样做并不是因为害怕 bash 插值,但是这样做是因为 $ 是一个元字符(EOL 后的锚定文本是无意义的——显然 sed 仍然理解其意图)。
猜你喜欢
  • 2010-11-02
  • 2016-11-09
  • 2014-06-25
  • 1970-01-01
  • 1970-01-01
  • 2022-12-27
  • 2010-11-20
  • 2014-08-03
  • 1970-01-01
相关资源
最近更新 更多