Sed: Complex replacement after drawing (on the same line)

Suppose you have the following text:

foobar 42 | ff 00 00 00 00 foobaz 00 | 0a 00 0b 00 00 foobie 00 | 00 00 00 00 00 bar 00 | ab ba 00 cd 00 

and you want to change everything not 00 on the right side | for wrapping with () , but only if on LHS | there is 00 . Desired Result:

  foobar 42 | ff 00 00 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobie 00 | 00 00 00 00 00 bar 00 | (ab) (ba) 00 (cd) 00 

Is there a good way to get around this with sed, or am I trying to stretch beyond the language?

Here is my job:

s/[^0]\{2\}/(&)/g wraps your RHS values

/[^|]*00[^|]*|/ can be used as the command address for working with valid lines only

Now we need to formulate a command that is executed in part of the template space.

This is really not line-oriented, which may explain why I am having trouble getting an expression that works.

+4
source share
5 answers
 $ awk 'BEGIN{ FS=OFS="|" } $1~/ 00 /{gsub(/[^ ][^0 ]|[^0 ][^ ]/,"(&)",$2)} 1' file foobar 42 | ff 00 00 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobie 00 | 00 00 00 00 00 bar 00 | (ab) (ba) 00 (cd) 00 

If the string you want to look for ever becomes more complex than 2 0, here is a more widely extensible approach, since it does not require you to write a RE that negates the string:

 $ awk ' BEGIN{ FS=OFS="|" } $1 ~ / 00 /{ split($2,a,/ /) $2="" for (i=2;i in a;i++) $2 = $2 " " (a[i] == "00" ? a[i] : "(" a[i] ")") } 1 ' file foobar 42 | ff 00 00 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobie 00 | 00 00 00 00 00 bar 00 | (ab) (ba) 00 (cd) 00 
+5
source

This may work for you (GNU sed):

  sed -r '/^\s*\S+\s*00/!b;s/\b([^0][^0]|0[^0]|[^0]0)\b/(&)/g' file 

This ignores lines that do not begin with a word followed by 00. Then it inserts lines with the characters of round 2, which are neither 0, or contain 0 and non-0.

+3
source

Well, it seems (although I do this all the time) that connecting sed with sed in sed means that I did not do it right the first time: here is one

 sed -r '/00.*\|/ { ## match lines with a zero before the pipe ### surround tailing digits with () ## s/(\w\w) (\w\w) (\w\w) (\w\w) (\w\w)$/(\1) (\2) (\3) (\4) (\5)/; ### replace the zeroes (00) with 00 ## s/\(00\)/00/g; }' txt 
  foobar 42 |  ff 00 00 00 00
   foobaz 00 |  (0a) 00 (0b) 00 00
   foobie 00 |  00 00 00 00 00
   bar 00 |  (ab) (ba) 00 (cd) 00

OK!

+2
source

Try it well!

 $ sed '/00 *|/ { h; s/|.*/|/; x; s/.*|//; s/\(0[1-9a-f]\|[1-9a-f][0-9a-f]\)/(\1)/g; H; x; s/\n//; }' yourfile.txt 

the output i get is this:

 foobar 42 | ff 00 00 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobie 00 | 00 00 00 00 00 bar 00 | (ab) (ba) 00 (cd) 00 

Edited, so do not touch line 00 to | .

+1
source

I think awk is probably the best tool for this to work, but this can be done with sed :

 sed '/^[^ ]* *00 *|/{ :a s/\(|.*[^(]\)\([0-9a-f][1-9a-f]\)/\1(\2)/ ta :b s/\(|.*[^(]\)\([1-9a-f][0-9a-f]\)/\1(\2)/ tb }' data 

The script searches for lines containing 00 before the pipe and only applies operations to those lines. There are two replacement operations, each wrapped in a loop. Lines :a and :b are labels. The ta and tb commands represent a conditional transition to the named label if a replacement has been made since the last transition. Two permutations are almost symmetrical; the first deals with any number that does not end with 0; the second deals with any number that does not start with 0; between them they ignore 00 . Samples look for the handset, any character sequence that does not end with an open parenthesis ( , and the corresponding pair of numbers; it replaces it so that the number ends in parentheses. Loops are necessary because the g modifier does not start from the beginning again, and the patterns work back through the numbers .

Given this data file (slightly extended version):

 foobar 42 | ff 00 00 00 00 foobaz 00 | 0a 00 0b 00 00 foobie 00 | 00 00 00 00 00 bar 00 | ab ba 00 cd 00 fizbie 00 | ab ba 00 cd 90 fizzbuzz 00 | ab ba 00 cd 09 

output from script:

 foobar 42 | ff 00 00 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobie 00 | 00 00 00 00 00 bar 00 | (ab) (ba) 00 (cd) 00 fizbie 00 | (ab) (ba) 00 (cd) (90) fizzbuzz 00 | (ab) (ba) 00 (cd) (09) 

To add an educational average p after each of the wildcard commands so that you can see how the wildcard works:

 foobar 42 | ff 00 00 00 00 foobaz 00 | 0a 00 (0b) 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobaz 00 | (0a) 00 (0b) 00 00 foobie 00 | 00 00 00 00 00 bar 00 | ab ba 00 (cd) 00 bar 00 | ab (ba) 00 (cd) 00 bar 00 | (ab) (ba) 00 (cd) 00 bar 00 | (ab) (ba) 00 (cd) 00 fizbie 00 | ab ba 00 (cd) 90 fizbie 00 | ab (ba) 00 (cd) 90 fizbie 00 | (ab) (ba) 00 (cd) 90 fizbie 00 | (ab) (ba) 00 (cd) (90) fizbie 00 | (ab) (ba) 00 (cd) (90) fizzbuzz 00 | ab ba 00 cd (09) fizzbuzz 00 | ab ba 00 (cd) (09) fizzbuzz 00 | ab (ba) 00 (cd) (09) fizzbuzz 00 | (ab) (ba) 00 (cd) (09) fizzbuzz 00 | (ab) (ba) 00 (cd) (09) 
+1
source

Source: https://habr.com/ru/post/1497901/


All Articles