【问题标题】:Bash replace line in a file with multiline fileBash用多行文件替换文件中的行
【发布时间】:2020-01-07 17:49:23
【问题描述】:

我有一个包含一些占位符值的文本文件:

例子:

Parent:
   Child: x
   Child2: <place-holder>

Car:
   Seat: x
   Door: <place-holder>

我正在使用sed 以一种适用于 MacOS 和 Linux 的方式完成此操作

sed -i .bak "s/<place-holder>/$REPLACEMNET_VALUE/g" file.yml

我现在需要更进一步,在这个文件中注入一个部分。

我有一个文件,其中包含格式正确的多行文件以及该文件在环境变量中的位置。

sed -i .bak "s/<place-holder-section>/$(<$CONFIG_OPTIONS_TEMP)/g" config.yml

但是,sed 似乎无法处理多行(不转义)。

错误:

sed: 1: "s/<place-holder-section>/ f ...": unescaped newline inside substitute pattern

这可能可以通过一些循环和 grepping 来解决行位置等问题,但我希望也许有人有一个更优雅的解决方案,可能使用 awk?保持 MacOS 的交叉兼容性也是一个问题。

【问题讨论】:

  • 请将该示例输入的所需输出(无描述)添加到您的问题(无评论)。

标签: bash awk sed


【解决方案1】:

Sed 有另一个命令“r 文件名”“附加从文件名读取的文本”。因此,如果要插入的所有文本本身都在一个文件中,则可以使用此 sed 命令。

例子:

bjb@blueeyes:~$ cat /tmp/old
Parent:
  Child: x
  Child2: <place-holder>

Car:
  Seat: x
  Door: <place-holder2>


<foo>


bjb@blueeyes:~$ cat /tmp/new
CarSeat:
    padding: fluff
    belt:  seat-belt-stuff

bjb@blueeyes:~$ sed '/<foo>/ {
> x
> r /tmp/new
> }' /tmp/old
Parent:
  Child: x
  Child2: <place-holder>

Car:
  Seat: x
  Door: <place-holder2>



CarSeat:
    padding: fluff
    belt:  seat-belt-stuff



bjb@blueeyes:~$ 

sed 命令指向文件 /tmp/old 中的标记 - 它将该行放在保持空间中并且从不检索它,因此它具有将标记替换为文件 /tmp/new 的内容的效果。

【讨论】:

  • 是的,r。为什么是x 而不是d
  • @stevesliva 看到我对为什么d 无法继续r 命令的回答。另请注意,x 命令将在插入文件之前在最终文件中引入一个额外的换行符。
  • @brenda 谢谢!我确信这是正确的答案。我想知道你是否可以帮助我解决最后一件似乎让我感到困惑的事情。我正在尝试在 bash 脚本中使用它,它似乎可以工作,但是正如您的示例所示,新文件通过管道传输到标准输出。在“/tmp/old”之后,我添加了“> /tmp/old”,我认为它会用新信息覆盖旧文件,但由于某种原因,这会产生一个没有输出的空白文件(预期没有输出)。您是否对为什么似乎无法重定向有任何见解?
  • ^ 解决方案。使用“| tee 文件名”
  • @Kyle.Tryon,当您发出类似sed 's/tu/ff/' /tmp/old &gt; /tmp/old 的命令时,bash 首先清除 /tmp/old,然后运行 ​​sed 并从(新清空的)/tmp/old 读取 - 这就是为什么它没有用。如果要就地编辑 /tmp/old,可以使用另一个 sed 选项“-i”:sed -i 's/tu/ff' /tmp/old
【解决方案2】:

这可能对你有用(GNU sed):

sed -e '/<foo>/{r insertFile' -e 'd}' file

遇到包含&lt;foo&gt; 的行时,将其替换为insertFile 的内容。

注意该解决方案由两部分组成:r insertFile 通常需要以换行符结尾,但-e 选项可以模拟这一点,因此第二部分同样引入了另一个删除找到的行的-e 选项。 d 也必须是最后一个命令,因为它后面的任何其他命令永远不会被执行。

【讨论】:

    猜你喜欢
    • 2016-11-20
    • 2012-10-22
    • 2019-07-19
    • 2012-01-10
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 2014-02-03
    • 2016-01-20
    相关资源
    最近更新 更多