1
PIN A
1 1:3 0:8
0 0:0

PIN B
1 1:0
0 0:0
Z Z:0

PIN C
1 1:3 0:8
0 0:0
Z Z:0

I would like to change the content on PIN A & PIN C only without affecting PIN B to

0 0:3
Z 0:3

Can't seem to find a way to replace without affecting the contents in PIN B using universal search and replace method:

perl -i -pe 's/0:0/0:3/g;' text
perl -i -pe 's/Z:0/Z:3/g;' text

Desired Output:

PIN A
1 1:3 0:8
0 0:3

PIN B
1 1:0
0 0:0
Z Z:0

PIN C
1 1:3 0:8
0 0:3
Z Z:3

1 Answer 1

2

You can use the paragraph mode with -00 where records are delimited by empty lines and do something like:

perl -00 -i -pe 's/\b[0Z]:\K0\b/3/g if /^PIN (A|C)\b/' text

(or just if /^PIN [AC]\b/ for single letter PINs).

Or:

perl -00 -i -pe 's/\b[0Z]:\K0\b/3/g unless /^PIN B\b/' text

A more generic approach is to record the current PIN in a variable, and do the substitution when that variable has the value you want:

perl -i -pe '
  if (/^PIN (.*)/) {
    $pin = $1;
  } else {
    s/\b[0Z]:\K0\b/3/g unless $pin eq "B";
  }' text

That s/\b[0Z]:\K0\b/3/g replaces the trailing 0 in [0Z]:0 (where \K is used to mark the start of what is to be Kept (and thus replaced) from the match) with 3 provided they're preceded and followed by word boundaries to avoid it matching 0:0 inside 10:02 for instance. That won't stop it matching inside 1:0:0.3 though as : and . are not word characters so there is a word boundary between : and 0 and between 0 and ..

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .