sed替换多行并输出到同一文件

时间:2015-04-22 22:51:22

标签: bash shell awk sed

我有一个如下文本文件

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

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

以上2个代码块,我想编写一个多行的sed命令,可以替换' name'和'网络'信息,然后将其重定向到同一个文件

我在下面试过

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 expert plesae阐明了如何使用sed命令替换多个内容并将输出重定向到temp.txt文件?

谢谢

3 个答案:

答案 0 :(得分:2)

您的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 one-liner括在单引号中,并从每个替换中删除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

答案 1 :(得分:1)

sed is the wrong tool for any task involving multi-line blocks of input because it's line-oriented. You should be using awk as it's record-oriented and so can treat each multi-line block of input a easily as sed can handle lines of input.

$ 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

Run it as awk '...' file > tmp && mv tmp file to change the original file, or you can use awk -i inplace '...' file if you have GNU awk 4.*.

答案 2 :(得分:0)

如果您只是尝试交换文本,我可能会链接seds,然后将输出存储在一个临时文件中,然后将其重新保存到原始文件中 - 可能不是最佳解决方案,但它的首先想到的是。

我在script.sh中有这个。

SKIP LOCKED

然后你可以简单地运行:

#!/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

希望有所帮助。