SED multiple find and replace

Hi,

searched through the forums and not really found what I am looking for. I am a bit of novice when it comes to anything above basic scripting and not even that when it comes to the sed command.

I have been reading the tutorials online but still struggling to get what I need :wall:

I have a script that has the following output (a small example of the full file):

example.txt

 
092F 1639163_Cluster01_Prod
0522 1639163_Cluster02_Prod
08C2 1639163_Cluster07_Prod
0957 1639163_Cluster07_Prod
1762 1024477_Cluster07_Prod
1767 1024477_Cluster07_Prod
176C 1024477_Cluster07_Prod
1771 1024477_Cluster07_Prod
1776 1024477_Cluster07_Prod
1EDC 1639163_Cluster07_Prod
1EE4 1639163_Cluster07_Prod
07F0 2048953_Cluster11_Prod
0807 1228838_Cluster11_Prod
175C 1229372_Cluster11_Prod
1B68 1024477_Cluster11_Prod
1E87 1639163_Cluster11_Prod
1D2B 1010831_SRV93012
1D6A 1045688 SRV93013
143E  34856 RS6PUNI01_Cluster
143F  34856 RS6PUNI01_Cluster
1440  34856 RS6PUNI01_Cluster
1441  34856 RS6PUNI01_Cluster
1442  34856 RS6PUNI01_Cluster
1443  34856 RS6PUNI01_Cluster
 

What I want to do is replace the "_" with a space between the numbers and the server names e.g.
from:
1639163_Cluster11_Prodto:
1639163 Cluster11_Prod

now I have been able to do this by using the command:

sed 's/1639163_/1639163 /g' example.txt

I am not sure if there is a better way of doing this but if there is not how do I do a multiple search and replace for the other sized devices within the one command - e.g.:
sed 's/2048953_/2048953 /g' example.txt
sed 's/1228838_/1228838 /g' example.txt
sed 's/1024477_/1024477 /g' example.txt

etc, etc.

I also want the changes to update the example.txt file - is this possible?

Thanks for your help.

Col

If the field to be changed is always the second one (numbered as whitespace-separated) then you could do:

awk '{ sub ("_", " ", $2); print}' infile

Alternatively, if your server names have a defined format like Cluster<NN> you could use:

sed 's/_\(Cluster[0-9][0-9]*\)/ \1/' infile
1 Like

man sed (linux) is a good choice:

sed -e 's/ \([0-9][0-9]*\)_/ \1 /'

However, sed does not allow you to edit in place, you will have to do something like:

sed .... oldfile > newfile
mv newfile oldfile

If I were writing the script, I would do:

#! /bin/ksh

for file in "${@}"; do
    temp=$(mktemp --tmpdir=$(dirname ${file}))
    sed -e 's/..../..../' ${file} > ${temp}
    mv ${temp} ${file}
done

Now using man mktemp (linux) may be a bit of overkill, but it guarantees that you are not overwritting an existing file. And the --tmpdir option ensures the man mv (linux) does not have to copy the file between filesystems.

You use -i option to edit the file directly using sed.

man sed

--ahamed

GNU sed does - -i option.

1 Like

Carlo apologies for being a bit supid here but what does the infile but at the end do - not sure I understand that?

Unfortunately I also have servers called - SRV{followed by 5 numbers} - so maybe not as straight-forward as I was hoping.

infile is just your input file, whatever it's called.

Try this in that case... I mean server name issue... :smiley:

sed 's/_\([[:alpha:]]*[0-9][0-9]*\)/ \1/' input_file

--ahamed

Hey All,

Thanks for the assist - this is works a treat.

However just so I understand can you give me a brief explaination of some of the switch options you used:

sed 's/_\
what does the _\ do?

([[:alpha:]]*[0-9][0-9]*
I assume this means any alpha character followed by a number between 0-9 and and another number 0-9 and * means anything?

as per my understanding if you are looking for multiple replacement and change in a single command this shall work
sed -e "s/cat/lion/g" -e "s/yes/no/g' -e 's/true/false/g' -e ....... -i.backup actual_file

will do all the replacement and keep a backup of your file, named actual_file.backup

offcourse its up to you, how good you are able to write the regular expression, more accurate less errors and surprises, but it will be fun, welcome to sed
its tricky first time, try to keep a backup manually :slight_smile:

_ is just an underscore.

\( ... \) marks a sub-pattern, and stores the matched text for later use ( \1 in the replacement text).

* is 0 or more occurrances of the previous regular expression.

[[:alpha:]]*[0-9][0-9]* - 0 or more alphabetic characters followed by 1 or more digits.