sed 's/^i/o/;H;1h;$!d;x;q' <infile >>infile
Se o arquivo for pequeno o suficiente para caber na memória, o acima deve funcionar. Não consigo pensar em nenhum motivo pelo qual você possa ter um problema de codificação, a menos que seu sed
esteja com bugs. Um sane sed
deve manipular qualquer codificação de caracteres válida que você queira lançar nele.
Se não for pequeno o suficiente para caber na memória, então em um sistema que entende os /dev/fd/[num]
links (que é praticamente qualquer sistema similar ao Unix) , e dado um shell que usa arquivos tmp para here-documents e não pipes (que é a maioria deles, para incluir o shell Bourne, bash
e zsh
mas não yash
ou ash
variantes como como BSD sh
, dash
ou busybox sh
que usam pipes em vez disso), e espaço livre ${TMPDIR:-/tmp}
suficiente para armazenar o buffer enquanto ele está sendo editado, então o seguinte deve funcionar:
sed -nf- file <<"" >>file
s/^i/o/
w /dev/fd/0
$r /dev/fd/0
Isso funcionará porque o shell obterá um arquivo temporário e um descritor de arquivo para o here-document, gravará o script sed
nele, unlink()
o arquivo temporário (e, portanto, removerá seu um e somente link no sistema de arquivos) , bifurque sed
como um filho para herdá-lo, e restaure seu próprio estado para o estado em que estava antes de chamar sed
- e então elimine seu próprio descritor para temp Arquivo. Nesse ponto, o arquivo existe apenas como descritor de stdin de sed
, e o kernel é obrigado a manter o arquivo apenas enquanto existir algum identificador para ele, mas assim que todos os descritores forem liberados, ele removerá um arquivo com 0 links do sistema de arquivos.
Então, sed
lerá seu script a partir do temp -f
ile excluído e truncá-lo-á como seu arquivo w
rite denominado - que é apenas um link para o arquivo excluído a partir do qual leu seu script - e antes de puxar cada linha de entrada, ele irá escrever uma cópia de seu espaço padrão. sed
irá autoprint -n
othing, mas na sua última linha de entrada $
, r
levará ao seu stdout o arquivo para o qual ele tem w
riting o tempo todo - e isso será >>
acrescentado à sua edição nomeada file
.
Quando sed
terminar e seu processo terminar, o último descritor restante para a fonte <<""
here-doc será fechado, e o kernel limpará posteriormente o arquivo. Enquanto isso, nenhum outro processo terá qualquer meio de acessar o arquivo e, portanto, está imune a qualquer possibilidade de outro processo afetar de alguma forma o buffer de trabalho de sed
.
Se -nf-
não funcionar, provavelmente é porque o seu sed
não interpreta -
para significar stdin (embora a maioria faça) e você deve usar -nf/dev/fd/0
.