【问题标题】:Replace each line with different text using 'sed' (shell script)使用“sed”(shell 脚本)将每一行替换为不同的文本
【发布时间】:2016-05-07 06:31:01
【问题描述】:

我有一个具有以下结构的 XML 文件:

    <root>
       <station name = "insert_text"/>
       <station name = "insert_text"/>
       <station name = "insert_text"/>
    </root>

我想用文本文件中的值替换文本“insert_text”,如下所示:

    Station1
    Station2
    Station3

读取上面的输入文件后,生成的 XML 文件应如下所示:

    <root>
       <station name = "Station1"/>
       <station name = "Station2"/>
       <station name = "Station3"/>
    </root>

我现在使用的脚本如下,它仅将所有 3 行替换为“Station1”。

    while read a
    do 
        sed -i -e "s/insert_text/$a/g" filename.xml
    done<inputfile.txt

为了将 XML 文件中的每一行替换为不同的文本,我应该进行哪些更改?

【问题讨论】:

标签: shell unix replace sed


【解决方案1】:

另一个 awk 对此进行了处理...与其将一个文件读取到内存中的数组中,然后读取第二个文件以替换文本,您可以同时流式传输这两个文件:

$ cat inp1
Station1
Station2
Station3
$ cat inp2
    <root>
       <station name = "insert_text"/>
       <station name = "insert_text"/>
       <station name = "insert_text"/>
    </root>
$ awk -vtext="insert_text" '$0~text{getline stn <"inp1"; sub(/insert_text/,stn)} 1' inp2
    <root>
       <station name = "Station1"/>
       <station name = "Station2"/>
       <station name = "Station3"/>
    </root>

如果您的电台列表超出您的内存容量,这种方法将非常有用。

为了便于阅读,脚本的作用如下:

$0 ~ text {                 # run these commands if we find your text
  getline stn <"inp1"       # read a new input line from the file "inp1"
  sub(/insert_text/,stn)    # do the substitution.
}
1                           # shorthand for "print the current line".

【讨论】:

    【解决方案2】:

    问题

    您的代码的问题是,一旦它替换了文件中的insert_text,就没有更多的insert_texts 可以被Station2Station3 替换。

    解决方案

    解决方案是在第一个insert_text 被替换后退出替换,并从文件中读取下一行

    你可以这样做

    while read a;     
    do          
       sed  "1,/insert_text/ s/insert_text/$a/; " input;     
    done < file
    

    它有什么作用?

    • 1,/insert_text/ 这是一个地址范围,告诉 sed 从第 1 行到第一个 insert_text 进行替换。没有其他 insert_texts 被替换

    sed  "/insert_text/{s/insert_text/$a/;q;}" input;
    

    【讨论】:

    • 好方法,但我会用sed "/insert_text/{s//$a/g; q;}"实现它
    • @WilliamPursell 是的,这应该在 gnu-sed 中工作,我在 BSD sed 中进行测试,但无法使其工作。
    • P.S.:BSD Sed 要求块中的最后一个命令以; 终止,这与 GNU Sed 不同(... q; }{ ... q })。这就是为什么@WilliamPursell 的命令甚至适用于 BSD Sed,但您在答案中引用的命令却没有。还要注意他在s// 调用中省略了正则表达式,它方便地重用了用于匹配该行的那个。
    • @mklement0 - 我只是想指出这一点;你打败了我。感谢您为我们 BSD 用户保持火炬燃烧。 ;-)
    • @mklement0 ; 是我错过的东西 :(。感谢s// 将替换已经匹配的模式的提示。这对我来说是新的
    【解决方案3】:

    我认为awk 更适合这项任务:

    演示

    $ cat inputfile.dat 
    Station1
    Station2
    Station3
    $ cat filename.xml 
       <root>
           <station name = "insert_text"/>
           <station name = "insert_text"/>
           <station name = "insert_text"/>
        </root>
    
    
    $ awk 'NR==FNR{a[++c]=$1;next}/station name/{sub("insert_text",a[++i])}1' inputfile.dat filename.xml 
       <root>
           <station name = "Station1"/>
           <station name = "Station2"/>
           <station name = "Station3"/>
        </root>
    

    【讨论】:

      猜你喜欢
      • 2020-02-14
      • 1970-01-01
      • 2015-08-30
      • 2017-04-30
      • 1970-01-01
      • 2014-02-09
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多