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