sed os sinais “e” e “g” não funcionam juntos

6

Dado isso:

echo AAA | sed -r 's/A/echo B/ge'

Eu entendo isso:

Becho Becho B

Eu teria pensado em obter "BBB". Isso é com o GNU sed versão 4.2.1. O que está acontecendo e como posso usar o sinalizador de execução e ter várias substituições podem ocorrer em uma linha (do shell, não do perl et al)?

    
por spinkus 24.01.2015 / 06:19

4 respostas

6

As bandeiras funcionam juntas no caminho oposto ao que você está esperando. A documentação de /e é , para o registro:

This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a nul character. This is a GNU sed extension.

Isso é um pouco tortuosamente escrito. O que significa é que, após a conclusão de um comando s/// para esta linha, se houve uma mudança, a (nova) linha é executada como um comando e sua saída é usada como substituta para esta linha.

Então, para o seu comando:

echo AAA | sed -r 's/A/echo B/ge'

primeiro substitui cada A por echo B e então executa o resultado como um comando. Tem (grosso modo) o mesmo efeito que:

echo AAA | sed -r 's/A/echo B/g' | sh

O GNU sed não suporta diretamente o modo que você deseja, embora você possa falsificá-lo com um script mais complexo, se desejado. Como alternativa, o modificador /e do Perl para seu comando s tem o comportamento que você está procurando, mas com expressões Perl.

    
por 24.01.2015 / 06:38
4

Você está recebendo várias substituições, mas você não recebe várias execuções. O padrão é executado assim que todas as substituições forem feitas.

Sem o e sinalizar o resultado de

echo AAA | sed -r 's/A/echo B/g'

é

echo Becho Becho B

Então essa é a linha de comando que é executada se você fizer incluir o e flag, que é equivalente a

echo 'Becho Becho B'
    
por 24.01.2015 / 06:38
2

Para obter 'BBB' de 'AAA' usando o comando 's' do GNU sed com o sinalizador 'e', pode-se fazer isso:

echo AAA | sed -re 's/A/echo -n B;/ge'

O 'AAA' é substituído por 'echo-nB; echo-nB; echo -n B; ', que, quando eventualmente executado, leva a 3 comandos de eco sequencialmente em execução, um para cada uma das correspondências globais. O '-n' omite os caracteres de alimentação de linha da saída do eco, fazendo com que os 'B's acabem em uma linha (mas sed anexa um avanço de linha por si só quando finalmente imprime o espaço de padrão).

    
por 18.07.2018 / 23:42
0

Algumas coisas:

(1) O caso de uso exato que você descreve pode ser tratado com apenas

echo AAA | sed 's/A/B/g'

(2) Para execução, se for especificamente o que você quer (para um uso mais avançado do que apenas ecoar), você pode usar o e flag como o último passo:

echo AAA | sed -r 's/A/B/g;s/(.*)/echo /e'

(3) Se você deseja apenas executar o comando se o comando FIRST substitute substituir algo, use um branch:

echo AAA | sed -r 's/A/B/g;te;b;:e;s/(.*)/echo /e'

Eles funcionam apenas no GNU sed , conforme descrito acima. BSD sed (pelo menos a versão que tenho) não suporta a opção -r , e requer um fim de string para seguir um nome de ramificação. (Você pode contornar esse último ponto adicionando várias opções -e com argumentos.)

Observe que, com a entrada fornecida (AAA), esses três marcadores são todos funcionalmente idênticos. Mas se o comando echo fosse alterado para outra coisa, ou se a opção -n fosse passada para sed , você veria a diferença.

    
por 02.12.2015 / 04:49

Tags