How to change a character on a certain line without delimiters with awk

0

I have a file, and I would like to change a single character on lines 400 through 600. The character happens to be the 22nd character on each line. It is also the 5th column, so I tried the following:

awk '{if (NR>=400 && NR <=600) $5="B"; print}' file.txt

The problem is, between each column there is a precise number of spaces that get replaced by a single space when I do this. How can I change a single character without touching any other character, including delimiters, within a line range?

sodiumnitrate

Posted 2016-05-31T19:05:25.220

Reputation: 296

Answers

1

The elegant way is to treat each character a field. If you set FS to the empty string, awk will split them just that way. Then you can set the 22nd field to what you wish it to be. Just remember to set OFS to the empty string as well so that there be no spaces (default OFS) between all characters in the output.

awk -vFS="" -vOFS="" 'NR==400,NR==600 {$22="B"}; {print}'

Obviously, this one will do unnecessary splitting on lines out of the range. We could set the field separators just before the 400th line and back after the 600th. But why split at all here when we have substr()? Let's just create a string with the first 21 characters + "B" + the rest of the original line for the important lines.

awk  '{s=$0}; NR==400,NR==600 { s=substr($0,1,21) "B" substr($0,23)}; {print s}'

(It's possible to do it without s, just by assigning $0 its new value but when we assign $0, it's re-split according to the rules, and no reason to sacrifice speed for that step now.)

Gombai Sándor

Posted 2016-05-31T19:05:25.220

Reputation: 3 325

0

You could also use sed:

sed -r '400,600s/(.{21}).(.*)/\1B\2/' file.txt

Michael Vehrs

Posted 2016-05-31T19:05:25.220

Reputation: 255