如何使用 awk 更改某一行中没有分隔符的字符

如何使用 awk 更改某一行中没有分隔符的字符

我有一个文件,我想更改第 400 行到第 600 行上的一个字符。该字符恰好是每行的第 22 个字符。它也是第 5 列,因此我尝试了以下操作:

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

问题是,每列之间有精确数量的空格,当我这样做时,这些空格会被单个空格替换。我怎样才能更改单个字符而不触及行范围内的任何其他字符(包括分隔符)?

答案1

优雅的方法是将每个字符视为一个字段。如果您将 FS 设置为空字符串,awk 将以这种方式拆分它们。然后您可以将第 22 个字段设置为您希望的值。只需记住将 OFS 也设置为空字符串,以便输出中的所有字符之间没有空格(默认 OFS)。

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

显然,这个方法会对超出范围的行进行不必要的拆分。我们可以在第 400 行之前设置字段分隔符,在第 600 行之后设置字段分隔符。但是,既然有 substr(),为什么还要在这里拆分呢?让我们用前 21 个字符 + “B” + 原始行的其余部分创建一个字符串,用于重要的行。

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

(没有 s 也可以做到这一点,只需为 $0 分配其新值,但是当我们分配 $0 时,它会根据规则重新拆分,现在没有理由为该步骤牺牲速度。)

答案2

您还可以使用sed

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

相关内容