skyrocker
skyrocker

Reputation: 199

sed to replace multiple lines and output to same file

I have a text file like below

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

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

The above 2 blocks of code, I want to write a multi-line sed command which can replace 'name' and 'network' information and then redirect it to the same file

I tried below

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

The above command only replaces the 'network' part from the text file but doesnt replace the 'name' part.

sed/bash experts plesae shed some light on how should I use sed command to replaces multiple things and redirect output to a temp.txt file ?

Thank you

Upvotes: 1

Views: 3180

Answers (3)

Ed Morton
Ed Morton

Reputation: 203684

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.*.

Upvotes: 1

jackar
jackar

Reputation: 724

If you're just trying to swap text I'd probably chain seds and then store the output in a temporary file and then cat it back into the original file - probably not the best solution, but its the first that comes to mind.

I have this in a 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

Then you can simply run:

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

Hope that helps.

Upvotes: 0

Tom Fenech
Tom Fenech

Reputation: 74655

Your while read loop serves no purpose here. Your sed command actually does what you want already:

$ 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

Note that I've enclosed your sed one-liner in single quotes and removed the g modifiers from each of the substitutions, which are unnecessary as you only intend on performing one substitution per line.

It is unclear whether you're looking to overwrite the original file or not - you seem to be attempting to do both at the moment. If you want to overwrite your input file (and your version of sed supports it), you can use the -i switch:

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

This will overwrite file. Some version of sed require that you specify a suffix for a backup file:

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

In this case, file is still overwritten but a backup of the original is made in file.bak.

If you just want to output the result to a new file, a simple redirection is all you need:

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

Upvotes: 2

Related Questions