BSD sed vs GNU - é capaz de aninhar correspondências?

4

Isso funciona perfeitamente em qualquer Linux:

$ echo foo bar | sed -n '/foo/{/bar/{;p;}}'
foo bar

Mas falha na antiga variante BSD do OSX:

❯  echo foo bar | sed -n  '/foo/{/bar/{;p;}}' 
sed: 1: "/foo/{/bar/{;p;}}": extra characters at the end of } command

Eu estou sentindo falta de algum encantamento mágico? Existe uma maneira de escrever isso de uma maneira portátil?

Eu odiaria ter que reverter para um pipeline de comandos grep | grep | grep .

Atualização: baixa reputação aqui, então não pode ser votada, mas agradece a todos os respondentes pelo seu conselho bem ponderado.

    
por Bryan Hunt 16.05.2018 / 17:56

2 respostas

5

Um comando de edição sed deve ser finalizado por ; ou uma nova linha literal. O GNU sed é muito indulgente com isso.

Seu script:

/foo/{/bar/{;p;}}

Expandido:

/foo/{
    /bar/{
        p
    }
}

Isso funcionaria como um script sed alimentado para sed a -f .

Se nos certificarmos de substituir as novas linhas com ; (necessário apenas no final dos comandos e {...} grupos de comandos) para que possamos usá-lo na linha de comando, obtemos

/foo/{/bar/{p;};}

Isso funciona com o OpenBSD sed (o original não, devido a esse segundo ; ausente).

Neste caso particular, isso pode ser ainda mais simplificado para

/foo/{/bar/p;}
    
por 16.05.2018 / 18:02
2

Isso parece funcionar no BSD sed :

$ echo -e "foo bar\nfoo\nbar" | sed -n '/foo/{/bar/p;}'
foo bar

Como duas camadas de aninhamento:

$ echo -e "foo bar\nfoo\nbar" | sed -n '/foo/{/bar/{p;};}'
foo bar
    
por 16.05.2018 / 18:02