user2491552
user2491552

Reputation: 71

Replace a specific pattern with SED

I need help on how to write a SED one liner (no awk) that replaces a substring of one line with a pattern in the same length. For example, if the file looks like:

daemon www X=1 ***Y=1,2,2*** Z=
daemon www X=1 ***Y=1,2,2,1,3,4,5*** Z=4
daemon mail a=3

I would like to change only lines that contain "daemon www" and the substring Y=.. with same number of zeros. (The number of #,#,#,# is unknown).

Output file should look like:

daemon www X=1 ***Y=0,0,0*** Z=4
daemon www X=1 ***Y=0,0,0,0,0,0,0*** Z=4
daemon mail a=3

Any ideas ? Thanks !

Upvotes: 3

Views: 272

Answers (4)

perreal
perreal

Reputation: 98118

One way:

 sed '/daemon www.*Y=/{:l s/\(Y=\(0,\)*\)[0-9]*/\10/;/Y=\(0,\)*0\([^,0-9]\|$\)/!bl}' input

some explanation:

if this line contains daemon www and Y=        #  /daemon www.*Y=/{
    loop                                       # :l
      a. find Y= and zeros followed by commas  # s/\(Y=\(0,\)*\)
      b. find a series of digits               # [0-9]*
      c. replace matches in 'a' and 'b' with   # /\10/g
         'a' and 0 
      d. jump to loop if cannot match the 
         desired pattern: Y=0,0..,0            # /Y=\(0,\)*0
      e. and the pattern in d ends with a 
         non-digit non-comma character or the 
         end of line                           # \([^,0-9]\|$\)/!bl

Upvotes: 4

Fredrik Pihl
Fredrik Pihl

Reputation: 45670

Try:

sed '/^daemon www.*Y/{s/[0-9]\([,*]\)/0\1/g}'

in action:

$ cat input
daemon www X=1 ***Y=1,2,2*** Z=
daemon www X=1 ***Y=1,2,2,1,3,4,5*** Z=4
daemon mail a=3

$ sed '/^daemon www.*Y/{s/[0-9]\([,*]\)/0\1/g}' input
daemon www X=1 ***Y=0,0,0*** Z=
daemon www X=1 ***Y=0,0,0,0,0,0,0*** Z=4
daemon mail a=3

Upvotes: 2

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89639

Try this:

sed -e 's/^\(daemon www X=1 .*Y=\)[0-9]\+/\10/' -e 's/,[0-9]\+/,0/g'

Upvotes: 0

jaypal singh
jaypal singh

Reputation: 77185

I would use awk. But you can disregard it if you really really have to use sed.

awk '/daemon www.*Y=*/{for(i=1;i<=NF;i++) ($i~/Y=/)?gsub(/[0-9]/,"0",$i):$i}1' file

Test:

$ cat file
daemon www X=1 ***Y=1,2,2*** Z=
daemon www X=1 ***Y=1,2,2,1,3,4,5*** Z=4
daemon mail a=3 Y=3,45,
$ awk '/daemon www.*Y=*/{for(i=1;i<=NF;i++) ($i~/Y=/)?gsub(/[0-9]/,"0",$i):$i}1' file
daemon www X=1 ***Y=0,0,0*** Z=
daemon www X=1 ***Y=0,0,0,0,0,0,0*** Z=4
daemon mail a=3 Y=3,45,

Upvotes: 2

Related Questions