I have a file something like this:
H|ACCT|XEC|1|TEMP|20130215035845 849002|48|1208004|100|||1 849007|28|1208004|100|||1 T|2|3
Note that there are extra empty lines at the end of the file.
I want to replace the value of column 5 with column 4's value in all the lines except first and last non-blank line.
I cannot rely on the number of fields as the last line may have as many fields as the other ones, nor on the lines to modify always starting with a number.
I tried the code below:
awk 'BEGIN{FS="|"; OFS="|"} {$5=$4; print}' in.txt
Output is:
H|ACCT|XEC|1|1|20130215035845
||||
849002|48|1208004|100|100||1
||||
849007|28|1208004|100|100||1
||||
T|2|3||
||||
||||
||||
Expected output:
H|ACCT|XEC|1|TEMP|20130215035845| 849002|48|1208004|100|100||1 849007|28|1208004|100|100||1 T|2|3
How can I skip the first and last non-blank lines from getting changed? I also want to skip blank lines.
Best Answer
Here you go with
awk
and processing the file only once.Explanation:
Here we are skyping first line to being replace 5th field's value with 4th field's value, and just print it and do
next
.... if it (current next line) was not empty line (at least contains one field
NF
), then take a backup of whole line with a\n
ewline addedl="\n"$0
first next set 5th field's value with 4th field's value$5=$4
and last set it to a variablem
with a\n
ewline addedm="\n"$0;
; There is ac
variable as a counter flag and is used to determine the number of empty lines!NF{c++}
if no line with at least one field seen; Otherwisec=0
will reset this counter.Now we have modified line in
m
variable andm && NF{print m}
will print it where in the next stepawk
runs andm
has set and it's not on empty lines& NF
(this is used to prevent duplication on printing when empty line).At the end we are printing the untouched last line which we take backup every time before performing replacement
END{ print l; ...
and then number of empty lines which never seen a line with a field with loopingfor (; i++<c;)print }'
.That's much shorter if you don't need redundant empty lines.