Considerando tudo, devorar o arquivo inteiro pode ser o caminho mais rápido.
A sintaxe básica é a seguinte:
sed -e '1h;2,$H;$!d;g' -e 's/__YOUR_REGEX_GOES_HERE__...'
Lembre-se, devorar o arquivo inteiro pode não ser uma opção se o arquivo for tremendamente grande. Para esses casos, outras respostas fornecidas aqui oferecem soluções personalizadas que garantem o trabalho em um pequeno espaço de memória.
Para todas as outras situações de hack e slash, apenas o prefixo -e '1h;2,$H;$!d;g'
seguido pelo sed
argumento regex original praticamente faz o trabalho.
por exemplo
$ echo -e "Dog\nFox\nCat\nSnake\n" | sed -e '1h;2,$H;$!d;g' -re 's/([^\n]*)\n([^\n]*)\n/Quick \2\nLazy \1\n/g'
Quick Fox
Lazy Dog
Quick Snake
Lazy Cat
O que -e '1h;2,$H;$!d;g'
faz?
A 1
, 2,$
, $!
partes são linha especificadores que limite que linhas a seguinte directamente comando é executado.
1
: Apenas primeira linha
2,$
: Todas as linhas começando a partir do segundo
$!
: Todas as linhas, exceto a última
Tão expandido, é o que acontece em cada linha de uma entrada de linha N.
1: h, d
2: H, d
3: H, d
.
.
N-2: H, d
N-1: H, d
N: H, g
O g
comando não recebe um especificador de linha, mas o d
comando anterior possui uma cláusula especial " Iniciar próximo ciclo " e isso impede a g
execução em todas as linhas, exceto a última.
Quanto ao significado de cada comando:
- O primeiro
h
seguido por H
s em cada linha copia as referidas linhas de entrada no espaço de espera desed
s . (Pense em um buffer de texto arbitrário.)
- Depois,
d
descarta cada linha para impedir que essas linhas sejam gravadas na saída. O espaço de espera, no entanto, é preservado.
- Por fim, na última linha,
g
restaura o acúmulo de todas as linhas do espaço de espera, para que sed
seja possível executar sua regex em toda a entrada (em vez de ser linha por vez) e, portanto, poder combinar em \n
s.