Paul Dawson
Paul Dawson

Reputation: 1382

sed/awk look for pattern in string and change another pattern on the same line

I have an F5 bigip.conf text file in which I want to change the route domain from 701 to 703 for all lines showing "10.166.201." The route domain is represented by %701

10.166.201.10%701
10.166.201.15%701
10.166.201.117%701

I am able to do this with bash but the problem is that the "else printf" command (I've also tried echo), which is supposed to print out all other lines, incorrectly parses things like "\r\n" and leaves them as "rn"

#!/bin/bash

while read line
do
if [[ $line = *"10.166.201"* ]]; 
    then
printf '%s\n' "$line" | sed -e 's/701/703/'

else printf '%s\n' "$line"  

fi  

done < bigip.conf > bigip.conf_updated

Is there a way to stop printf and echo from modifying the "\r\n"?

Is there a better way to do this in sed/awk?

Thanks.

Upvotes: 1

Views: 245

Answers (4)

hek2mgl
hek2mgl

Reputation: 158230

Use a regexp address:

sed '/10\.166\.201\./s/%701/%703/' bigip.conf

Once you made sure that the command works for you, you can change the file in place using -i:

sed -i'' '/10\.166\.201\./s/%701/%703/' bigip.conf

With GNU sed you can omit the option value for -i:

sed -i '/10\.166\.201\./s/%701/%703/' bigip.conf

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204558

The clear, simple, robust, efficient way is:

awk 'BEGIN{RS=ORS="\r\n"; FS=OFS="%"} index($1,"10.166.201.")==1{ $2="703" } 1' file

Note that you don't need to escape the .s or anchor to avoid partial matches because the above simply treats the IP address as a string appearing at the start of the line. The above uses GNU awk for multi-char RS to preserve your \r\n line endings.

Upvotes: 1

RavinderSingh13
RavinderSingh13

Reputation: 133760

Following awk may help you on same.

awk '{gsub(/\r/,"")} /your_string/{sub(/701/,"703")} 1'   Input_file

Also in case you want to save output into same Input_file itself then do following:

awk '{gsub(/\r/,"")} /your_string/{sub(/701/,"703")} 1'  Input_file > temp_file && mv temp_file  Input_file

EDIT: In case your Input_file has \r in them then I added {gsub(/\r/,"")} in my above codes, in case you don't have them you could remove them from codes.

EDIT2: Changing string to your_string also change . to \. too in your address.

Upvotes: 1

heemayl
heemayl

Reputation: 42127

sed:

sed -E 's/(10\.166\.201\.[[:digit:]]+%70)1/\13/'
  • The captured group, (10\.166\.201\.[[:digit:]]+%70) matches 10.166.201. literally, then one or more digits, then %70 literally

  • Outside the captured group, 1 matches literally; in the replacement, the the captured group is used and 1 is replaced by 3

Example:

% cat file.txt
10.166.201.10%701
10.166.201.15%701
10.166.201.117%701

% sed -E 's/(10\.166\.201\.[[:digit:]]+%70)1/\13/' file.txt
10.166.201.10%703
10.166.201.15%703
10.166.201.117%703

Upvotes: 1

Related Questions