Como salvar o padrão correspondente na variável usando o comando 'sed'?

5

Estou tentando encontrar um padrão usando o comando sed em file.txt entre o primeiro char1 e char2 e substitua-o por string. como abaixo com o exemplo do modo echo :

echo "This X is test Y. But X is not test Y." | sed 's/X[^Y]*Y/REPLACE/'

Além disso, preciso salvar um padrão correspondente (como is test {& lt; - espaços ao redor é importante}) em uma variável.

    
por αғsнιη 24.10.2014 / 08:34

2 respostas

9

Aqui está uma única chamada de sed que escreve a linha revisada para stdout, enquanto ao mesmo tempo salva o texto removido na variável de shell var :

$ var=$(echo "This X is test Y. But X is not test Y." | sed -nr 'h;s/[^X]*X([^Y]*)Y.*//;p;x;s/X[^Y]*Y/REPLACE/;w /dev/stderr') 2>&1
This REPLACE. But X is not test Y.

O valor de var é:

$ echo "==$var=="
== is test ==

Explicação:

  • h

    Este comando copia o padrão atual para o espaço de espera.

  • s/[^X]*X([^Y]*)Y.*//;p

    Isso remove tudo do espaço padrão, exceto o texto entre os primeiros X e Y , incluindo os espaços. Isso é então impresso no stdout. Esta é a saída que é capturada pelo shell e atribuída a var .

  • x

    Isso copia o espaço de espera de volta para o espaço de padrão. Quando isso é feito, o espaço padrão contém uma cópia da linha de entrada original.

  • s/X[^Y]*Y/REPLACE/; w /dev/stderr

    A substituição é feita e o resultado é gravado em stderr .

  • 2>&1

    Após o shell ter capturado o stdout em var , isso instrui o shell a copiar stderr (que tem a linha com REPLACE) para stdout.

Além da manipulação da variável var

A variável var inclui os espaços iniciais e finais. Se o shell subseqüentemente submetesse var à divisão de palavras, esses espaços seriam removidos. Para evitar isso, quando var for referenciado, faça isso entre aspas duplas, como no exemplo acima.

    
por John1024 24.10.2014 / 08:55
3

Você precisa realizar isso com um segundo comando sed:

var=$(echo "This X is test Y. But X is not test Y." | \
tee >(sed 's/X[^Y]*Y/REPLACE/' >/dev/stderr) | \
sed -r 's/[^X]*X([^Y]*)Y.*//')

Exlanation:

  • Você precisa usar tee para dividir o fluxo. Que stdout e stderr contenham a sequência.
  • tee precisa de um arquivo como argumento. Damos a tee um canal em que sed escuta e substitui a string.
  • sed imprime a string para stderr : A saída que você vê no terminal.
  • O segundo comando sed ouve stdout e extrai a string necessária, que agora é salva na variável $var (o contect de stdout ).

Use isso para verificar:

$ echo ">$var<"
> is test <
    
por chaos 24.10.2014 / 08:42