A maneira elegante é tratar cada personagem de um campo. Se você definir FS para a string vazia, o awk irá dividi-los dessa maneira. Então você pode definir o 22º campo para o que você deseja que seja. Apenas lembre-se de configurar o OFS para a string vazia, de modo que não haja espaços (padrão OFS) entre todos os caracteres na saída.
awk -vFS="" -vOFS="" 'NR==400,NR==600 {$22="B"}; {print}'
Obviamente, este fará divisões desnecessárias em linhas fora do intervalo. Poderíamos definir os separadores de campo pouco antes da 400ª linha e depois do 600º. Mas por que dividir tudo aqui quando temos substr ()? Vamos apenas criar uma string com os primeiros 21 caracteres + "B" + o resto da linha original para as linhas importantes.
awk '{s=$0}; NR==400,NR==600 { s=substr($0,1,21) "B" substr($0,23)}; {print s}'
(É possível fazer isso sem s, apenas atribuindo $ 0 a seu novo valor, mas quando atribuímos $ 0, ele é re-dividido de acordo com as regras, e não há razão para sacrificar a velocidade para essa etapa agora.)