如何使用shell(bash)将一个文件中的文本块替换为另一个文件中的文本块

dhxwm5r4  于 2023-01-21  发布在  Shell
关注(0)|答案(3)|浏览(158)

我尝试用changes.xml的整个内容替换file_to_change.xml中的一个文本块,这是主文件的一个标记,有一个小的更改。
以下是file_to_change.xml的内容:

<clients>
    <client>
        <name>Bob</name>
        <age>18</age>
    </client>
    <client>
        <name>Alice</name>
        <age>12</age>
    </client>
    <client>
        <name>Carlos</name>
        <age>28</age>
    </client>
</clients>

下面是changes.xml的内容:

<client>
        <name>Carlita</name>
        <age>17</age>
    </client>

这是一个辅助文件的内容,其中包含了我想要更改的行:

<client>
        <name>Carlos</name>
        <age>28</age>
    </client>

我所寻找的解决方案与here所解释的解决方案之间最大的区别在于文件并不完全相同,同样重要的是,我所工作的环境不允许我使用外部工具,因此我试图找到一个“核心”解决方案,使用sed、awk等。
这是我试图使用的命令:

sed -i -e '1r changes.xml' -e '1,/r aux.xml/d' file_to_change.xml

我希望file_to_change. xml看起来像这样:

<clients>
    <client>
        <name>Bob</name>
        <age>18</age>
    </client>
    <client>
        <name>Alice</name>
        <age>12</age>
    </client>
    <client>
        <name>Carlita</name>
        <age>17</age>
    </client>
</clients>
rpppsulh

rpppsulh1#

用纯重击?

#!/bin/bash

file=$( < file_to_change.xml )
search=$( < aux.xml )
replacement=$( < changes.xml )

printf '%s\n' "${file/"$search"/$replacement}"
<clients>
    <client>
        <name>Bob</name>
        <age>18</age>
    </client>
    <client>
        <name>Alice</name>
        <age>12</age>
    </client>
    <client>
        <name>Carlita</name>
        <age>17</age>
    </client>
</clients>
ercv8c1e

ercv8c1e2#

我将按照以下方式利用GNU AWK完成此任务,让file.txt内容

ABC
DEF
GHI
JKL
MNO

file_detect.txt

GHI
JKL

file_replacement.txt

123
456
789

那么

awk 'BEGIN{RS=""}FILENAME=="file_replacement.txt"{repl=$0;next}FILENAME=="file_detect.txt"{find=$0;next}{place=index($0,find);print substr($0,1,place-1) repl substr($0,place+length(find))}' file_replacement.txt file_detect.txt file.txt

给出输出

ABC
DEF
123
456
789
MNO
    • 免责声明**:这个解决方案假设你在你的任何文件中从来没有空行,如果这不保持将RS改变为不存在于所涉及的任何文件中的任何值。

说明:首先我告诉GNU AWK,空行被认为是行分隔符,使用RS设置为空字符串,目的是让GNU AWK认为整个文件是一个大的单行。然后当我遇到名为file_replacement.txt的文件时,我简单地将其内容存储到名为repl的变量中,并指示GNU AWK转到next行。因此不执行其他操作,类似地,file_detect.txt内容存储在名为find的变量中。然后,我按照以下方式使用String functions:首先,index检测要替换的部分位于何处,然后使用substr获取要替换的部分之前的部分substr($0,1,place-1)和要替换的部分之后的部分substr($0,place+length(find),然后使用repl将它们连接起来。

    • 警告**:该解决方案假设在file.txt内正好有一个file_detect.txt
  • (在GNU Awk 5.0.1中测试)*
iugsix8n

iugsix8n3#

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

sed -Ez 's/.*/echo -n "@@@&@@@" | cat fileToSearch - fileReplacement/e
         s/^(.*)@@@(.*)\1(.*)@@@(.*)/\2\4\3/' file

相关问题