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 sedargumento 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 gcomando não recebe um especificador de linha, mas o dcomando anterior possui uma cláusula especial " Iniciar próximo ciclo " e isso impede a gexecução em todas as linhas, exceto a última.
Quanto ao significado de cada comando:
- O primeiro
hseguido por Hs 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,
ddescarta 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,
grestaura o acúmulo de todas as linhas do espaço de espera, para que sedseja possível executar sua regex em toda a entrada (em vez de ser linha por vez) e, portanto, poder combinar em \ns.