Melhor maneira de fazer “echo $ x | sed… ”e“ echo $ x | grep… ”

12

Eu geralmente encontro isso em scripts (e, tenho que admitir, eu mesmo escrevo):

a=$(echo "$x" | sed "s/foo/bar/")

ou

if echo "$x" | grep -q foo
then
    ...
fi

Considere "foo" para incluir algumas coisas de regex.

Eu sinto que deveria haver - e provavelmente é - uma maneira melhor de expressar isso, uma que não envolve dois comandos e um pipe, mas envolve a coisa em uma expressão mais compacta. / p>

Eu simplesmente não consigo encontrar. Alguém?

    
por DevSolar 04.02.2010 / 11:11

4 respostas

10

A menos que você assuma um shell específico, não há melhor maneira de fazer isso do que “pipe echo to tool” (ou apenas uma “ferramenta” como expr ); é tudo o que você pode realmente contar com o shell Bourne tradicional e / ou o Shell POSIX . Se você considerar outros shells, existem outras possibilidades embutidas.

ksh tem

  • padrões extras: ?(pattern-list) , *(pattern-list) , {n}(pattern-list) , {n,m}(pattern-list) , @(pattern-list) , !(pattern-list) ;
  • o especificador %P printf para converter uma expressão regular estendida em um padrão (e %R para expressão regular estendida para padrão);
  • a condição expr == pattern em [[ expr ]] tests;
  • a expansão do parâmetro ${param/pattern/replacement} .

bash tem

  • a opção extglob para ativar a maioria dos padrões extras de ksh (sem {n} e {n,m} );
  • a condição expr == pattern (em [[ expr ]] tests);
  • a expansão do parâmetro ${param/pattern/replacement} ;
  • (em versões mais recentes) a condição expr =~ extregexp (em [[ expr ]] tests) que pode corresponder às expressões regulares estendidas
    • com subexpressões entre parênteses e o parâmetro BASH_REMATCH , substituições no estilo sed poderiam ser feitas.

zsh tem

  • seus próprios padrões estendidos com a opção EXTENDED_GLOB ;
  • ksh - como padrões estendidos com a opção KSH_GLOB
  • a condição expr == pattern (em [[ expr ]] tests);
  • a expansão do parâmetro ${pattern/pattern/replacement} ;
  • a condição expr =~ extregexp (em [[ expr ]] tests) que pode corresponder às expressões regulares estendidas,
    • ele pode usar PCRE em vez de expressões regulares estendidas simples se a opção RE_MATCH_PCRE estiver definida,
    • com subexpressões entre parênteses, o parâmetro MATCH e o parâmetro match (ou BASH_REMATCH com o conjunto de opções BASH_REMATCH ), substituições no estilo sed poderiam ser feitas;
  • o módulo zsh/pcre que oferece os comandos pcre_compile , pcre_study e pcre_match e a condição -pcre-match teste (em [[ expr ]] testes);
  • o módulo zsh/regex que oferece a condição -regex-match teste (em [[ expr ]] testes).
por 04.02.2010 / 17:12
7
sed 's/foo/bar/' <<< "foobie"

grep 'this' <<< "this or that"

Embora as respostas de Dan McG sejam boas, elas não darão exatamente o mesmo suporte se você precisar.

    
por 04.02.2010 / 13:58
6

Para substituir a linha sed, faça algo como

${a/foo/bar} ou ${a//foo/bar}

No primeiro formulário, somente a primeira instância é substituída. A segunda forma é uma pesquisa global & substituir.

No seu caso, seria

Em vez de:

if echo $x | grep foo
then
    ...
fi

Considere o uso de:

if [ $x =~ foo ]
then
    ...
fi

Em que foo é uma expressão regular.

    
por 04.02.2010 / 11:36
2

Uma boa maneira compatível com o posix para testar se uma variável contém um padrão é:

test ${var##*foo*} || <do something>;

A sintaxe da expansão de parâmetros é:

 ${parameter##pattern}

em que pattern é um padrão de shell .

    
por 19.05.2010 / 06:09

Tags