>我有一个如下所示的文本文件
name: xyz
ip: x.x.x.x
network: abc
gateway: def
name: xyz
ip: x.x.x.x
network: abc
gateway: def
以上 2 个代码块,我想编写一个多行 sed 命令,它可以替换"名称"和"网络"信息,然后将其重定向到同一个文件
我在下面试过
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 专家 plesae 阐明了我应该如何使用 sed 命令替换多个内容并将输出重定向到临时文件.txt?
谢谢
您的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
sed
对于任何涉及多行输入块的任务都是错误的工具,因为它是面向行的。您应该使用 awk,因为它是面向记录的,因此可以轻松地处理每个多行输入块,因为 sed 可以处理输入行。
$ awk -v RS= -v ORS='nn' '{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
。
如果您只是想交换文本,我可能会链接 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
希望有帮助。