Reputation: 111
I have files with this kind of structure:
abc
def
ghi
...
x x y x x
x x z x x
x x y x x
...
JKL
x x y x x
x x z x x
x x y x x
...
...
*empty line*
mno
pqr
...
...
I would like to copy the whole file to a new file but with some changes. Fist, I want to affect only the lines between pattern JKL and the next empty line. On top of that, I need to replace every occurrence of the pattern y with a new pattern NEW, but only if it appears in the third column.
I tried using sed, but I got stuck at how to select columns:
sed -ne '/JKL/,/^$/s/y/NEW/'
this, of course, replaced y with NEW in all columns.
I also tried looking up awk, but I could only find examples of the two separate needs I have, and wasn't able to put them together. How could I do it?
Upvotes: 1
Views: 598
Reputation: 37424
Using GNU awk and split()
. First some more descriptive test data:
...
JKL
x x y x x
x y z x x
...
Then the script:
$ awk '
/JKL/,/^ *$/ { # the desired block
n=split($0,a,FS,seps) # split and store the separators
b=seps[0] # seps[0] has the leading space, init buffer with it
for(i=1;i<=n;i++) { # iterate all fields
if(i==3 && a[i]=="y") # if 3rd field is y
a[i]="NEW" # replace it with with NEW
b=b a[i] seps[i] # build the buffer for output
}
print b
}' file
and the output:
JKL
x x NEW x x
x y z x x
Upvotes: 0
Reputation: 23677
awk
also allows the range syntax similar to sed
, see How to select lines between two patterns?
for alternate and more flexible ways
awk '/JKL/,/^$/{if($3=="y") $3="NEW"} 1' ip.txt
/JKL/,/^$/
lines of interest
if($3=="y")
if 3rd field value is exactly the string y
$3="NEW"
change the 3rd field value to desired textsub(/y/, "NEW", $3)
or gsub(/y/, "NEW", $3)
1
idiomatic way to print contents of $0
Upvotes: 1
Reputation: 241988
Third column is something that follows the beginning of a line, a sequence of non-spaces, a spaces, another sequence of non-spaces, and finally a space:
sed '/^JKL$/,/^$/s/^\([^ ][^ ]* [^ ][^ ]*\) y /\1 NEW /'
or, if your sed supports -r
or -E
:
sed -E '/^JKL$/,/^$/s/^([^ ]+ [^ ]+) y /\1 NEW /'
Upvotes: 2