A maneira portátil de fazer isso - e a maneira mais eficiente - é com endereços. Você consegue fazer isso:
printf %s\\n cat dog pear banana cat dog |
sed -e '/cat/!{/dog/!b' -e '};cBear'
Dessa maneira, se a linha não contiver a string cat e não contiver as ranhuras para cães sed
b
do script, imprime automaticamente sua linha atual e puxa a próxima para iniciar o próximo ciclo. Portanto, ele não executa a próxima instrução - que neste exemplo c
trava a linha inteira para ler Bear, mas pode fazer qualquer coisa.
Provavelmente é importante notar também que qualquer declaração após a !b
em que sed
comando pode única corresponder em uma linha contendo tanto uma string dog
ou cat
- para que você possa realizar mais testes sem qualquer perigo de combinar uma linha que não faz - o que significa que agora você pode aplicar regras para apenas um ou outro também.
Mas é o próximo. Aqui está a saída do comando acima:
###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
Você também pode implementar de forma portável uma tabela de pesquisa com referências anteriores.
printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ cat dog /;x
};G;s/^\(.*\)\n.* \1 .*/Bear/;P;d'
É muito mais trabalhoso configurar para este exemplo simples, mas pode criar sed
scripts muito mais flexíveis a longo prazo.
Na primeira linha, x
altero o espaço de espera e o espaço do padrão e, em seguida, insiro o cão <space>
felino<space>
<space>
no espaço de espera antes de x
mudá-los de volta.
A partir de então e em todas as linhas seguintes, G
mantenha o espaço anexado ao espaço do padrão e verifique se todos os caracteres do início da linha até a nova linha que acabei de adicionar no final correspondem a uma sequência cercada por espaços após ela. Nesse caso, substituo o lote inteiro pelo Bear e, se não houver, não haverá danos, pois na próxima P
etapa, somente até a primeira nova linha que ocorrer no espaço do padrão, d
elimino tudo.
###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
E quando digo flexível, quero dizer isso. Aqui está substituindo gato por BrownBear e cachorro por BlackBear :
printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ 1cat Brown 2dog Black /;x
};G;s/^\(.*\)\n.* [0-9]\1 \([^ ]*\) .*/\2Bear/;P;d'
###OUTPUT###
BrownBear
BlackBear
pear
banana
BrownBear
BlackBear
É claro que você pode expandir bastante o conteúdo da tabela de pesquisa - peguei a ideia nos e-mails de Greg Ubben sobre o assunto quando, nos anos 90, ele descreveu como construiu uma calculadora grosseira a partir de uma única sed s///
declaração.
-r
opção como sinônimo de-E
para compatibilidade com GNU sed. O OpenBSD e OS Xsed -E
interpretarão o tubo escapado como um tubo literal, não como um operador de alternância. Aqui está um link para a página de manual do NetBSD e aqui está um para o OpenBSD que não tem dez anos.