У меня есть файл, и я хотел бы изменить один символ в строках с 400 по 600. Символ оказывается 22-м символом в каждой строке. Это также 5-й столбец, поэтому я попробовал следующее:

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

Проблема в том, что между каждым столбцом есть точное количество пробелов, которые заменяются одним пробелом, когда я делаю это. Как я могу изменить один символ, не касаясь других символов, включая разделители, в пределах диапазона строк?

2 ответа2

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, оно перераспределяется в соответствии с правилами, и теперь нет причин жертвовать скоростью для этого шага.)

0

Вы также можете использовать sed:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .