【问题标题】:sed to replace multiple lines and output to same filesed 替换多行并输出到同一个文件
【发布时间】:2015-04-22 22:51:22
【问题描述】:

我有一个如下所示的文本文件

name: xyz
ip: x.x.x.x
network: abc
gateway: def

name: xyz
ip: x.x.x.x
network: abc
gateway: def

以上两段代码,我想写一个多行的sed命令,可以替换'name'和'network'信息,然后重定向到同一个文件

我在下面尝试过

while read line; do

cat $line 2> /dev/null | sed -i s/xyz/abc/g;s/network:.*/network: temp_net/g test.txt > ~/temp-file.txt

done

上述命令仅替换文本文件中的“网络”部分,但不替换“名称”部分。

sed/bash 专家请阐明我应该如何使用 sed 命令替换多个内容并将输出重定向到 temp.txt 文件?

谢谢

【问题讨论】:

  • 请你edit你的问题来澄清你想要做什么?你想要的输出是什么?

标签: bash shell awk sed


【解决方案1】:

您的while read 循环在这里没有任何作用。您的 sed 命令实际上已经完成了您想要的操作:

$ cat file
name: xyz
ip: x.x.x.x
network: abc
gateway: def

name: xyz
ip: x.x.x.x
network: abc
gateway: def
$ sed 's/xyz/abc/; s/network:.*/network: temp_net/' file
name: abc
ip: x.x.x.x
network: temp_net
gateway: def

name: abc
ip: x.x.x.x
network: temp_net
gateway: def

请注意,我已将您的 sed 单行引号括在单引号中,并从每个替换中删除了 g 修饰符,这是不必要的,因为您只打算每行执行一次替换。

目前尚不清楚您是否要覆盖原始文件 - 您目前似乎正在尝试同时执行这两项操作。如果你想覆盖你的输入文件(并且你的 sed 版本支持它),你可以使用-i 开关:

sed -i 's/xyz/abc/; s/network:.*/network: temp_net/' file

这将覆盖file。某些版本的 sed 要求您为备份文件指定后缀:

sed -i.bak 's/xyz/abc/; s/network:.*/network: temp_net/' file

在这种情况下,file 仍会被覆盖,但会在 file.bak 中创建原始备份。

如果您只想将结果输出到新文件,只需简单的重定向即可:

sed 's/xyz/abc/; s/network:.*/network: temp_net/' file > new_file

【讨论】:

    【解决方案2】:

    sed 对于任何涉及多行输入块的任务来说都是错误的工具,因为它是面向行的。您应该使用 awk,因为它是面向记录的,因此可以轻松处理每个多行输入块,因为 sed 可以处理输入行。

    $ awk -v RS= -v ORS='\n\n' '{sub(/xyz/,"abc"); sub(/network:[^\n]+/,"network: temp_net")}1' file
    name: abc
    ip: x.x.x.x
    network: temp_net
    gateway: def
    
    name: abc
    ip: x.x.x.x
    network: temp_net
    gateway: def
    

    awk '...' file > tmp && mv tmp file 运行它来更改原始文件,或者如果你有GNU awk 4.*,你可以使用awk -i inplace '...' file

    【讨论】:

    • 在这种情况下将每个块视为记录有什么好处?
    • @TomFenech 当 OP 意识到他们只想对特定块进行转换时,他们可以简单地添加一个 /ip: a.b.c.d/ 或类似的子句。 OP的真实数据不可能是相同值的重复块。
    【解决方案3】:

    如果您只是想交换文本,我可能会链接 seds,然后将输出存储在一个临时文件中,然后将其转换回原始文件 - 可能不是最好的解决方案,但它是第一个解决方案介意。

    我在 script.sh 中有这个

    #!/bin/bash
    while read line
    do
    
    echo $line | sed s/xyz/temp1/g | sed s/abc/temp2/g | sed s/temp1/abc/g | sed s/temp2/xyz/g
    
    
    done < $1 > $2
    
    cat $2 > $1
    

    然后你可以简单地运行:

    chmod +x script.sh
    ./script.sh input.txt output.txt
    

    希望对您有所帮助。

    【讨论】:

    • sed 管道不是必需的。 sed 's/xyz/temp1/g;s/abc/temp2/g;s/temp1/abc/g;s/temp2/xyz/g' 将执行与您的管道相同的任务。
    猜你喜欢
    • 2019-03-22
    • 2017-11-08
    • 2013-04-21
    • 2018-10-04
    • 2020-11-19
    • 2017-09-08
    • 2019-07-09
    • 2021-07-09
    • 1970-01-01
    相关资源
    最近更新 更多