This is a follow-up question on my previous thread ( Update the second line after the matched row with reference values) with more advanced requirement. I have a master file main
that I wish to modify with 2 objectives:
(1) to find the MATCH LINE
phrase in main
, jump 2 lines down and replace the 3rd column with values given second column of the ref
file ;
(2) if a line has write output
phrase, replace its 4th column with similar replacement. So ref
has 2 columns: first one for the output filenames and 2nd one for the replacement values.
Please see below for the sample and desired output.
main file
one line here
This is the 'MATCH LINE'
# this is just a comment
Now this *** to be updated
write output label ***
another line here
ref file
Out1 ONE
Out2 TWO
Out3 THREE
desired outputs file1 (Out1)
one line here
This is the 'MATCH LINE'
# this is just a comment
Now this ONE to be updated
write output label ONE
another line here
desired outputs file1 (Out2)
one line here
This is the 'MATCH LINE'
# this is just a comment
Now this TWO to be updated
write output label TWO
another line here
desired outputs file1 (Out3)
one line here
This is the 'MATCH LINE'
# this is just a comment
Now this THREE to be updated
write output label THREE
another line here
My script is originated from Ed Morton @ed-morton who kindly helped me for the previous thread and I have modified it to adopt to new requirement but it gives me error. I appreciate your help.
#!/bin/awk -f
NR == FNR {
lines[++numLines] = $0
a[NR]=$2
if ( /\047MATCH LINE\047/ ) {
tgt1 = NR + 2
}
if ( /write output/ ) {
tgt2 = NR
}
next
}
{
for ( lineNr=1; lineNr<=numLines; lineNr++ ) {
line = lines[lineNr]
if ( lineNr == tgt1 ) {
#sub(/NUMBER/,$2,line)
line[$3]=a[FNR]
}
if ( lineNr == tgt2 ) {
line[$4]=a[FNR]
}
print line > $1
}
close($1)
}
./tst.awk main ref
Error:
scalar "line" cannot be used as array
Ed suggested to split the line into array, replace the right index and stitch them together; but the output looks weird. Here is the updated script and output.
#!/bin/awk -f
NR == FNR {
lines[++numLines] = $0
a[NR]=$2
if ( /\047MATCH LINE\047/ ) {
tgt1 = NR + 2
}
if ( /write output/ ) {
tgt2 = NR
}
next
}
{
for ( lineNr=1; lineNr<=numLines; lineNr++ ) {
line = lines[lineNr]
if ( lineNr == tgt1 ) {
#sub(/NUMBER/,$2,line)
numFlds = split(line,flds)
flds[3] = a[FNR]
for ( fldNr=1; fldNr<=numFlds; fldNr++ ) {
line = (fldNr==1 ? "" : line " ") flds[fldNr]
}
}
if ( lineNr == tgt2 ) {
numFlds = split(line,flds)
flds[4] = a[FNR]
for ( fldNr=1; fldNr<=numFlds; fldNr++ ) {
line = (fldNr==1 ? "" : line " ") flds[fldNr]
}
}
print line > $1
}
close($1)
}
Output
$ head Out*
==> Out1 <==
one line here
This is the 'MATCH LINE'
# this is just a comment
Now this line to be updated
write output label line
another line here
==> Out2 <==
one line here
This is the 'MATCH LINE'
# this is just a comment
Now this is to be updated
write output label is
another line here