Linha de comandos: extrair substring da saída

16

Digamos que eu execute o comando SayStuff

$ SayStuff

e a saída é

Watermelons and cucumbers

Agora. Digamos que eu queira extrair a substring cucumbers da saída e canalizá-la para algo.
A maneira que eu usaria isso programaticamente seria dividir a saída em uma matriz pelo delimitador Espaço e referenciá-la por ArrayName[2] . Eu sou relativamente novo em shell scripts e só consegui desenterrar exemplos de cut semi-enigmáticos, nenhum dos quais fazia sentido.

Alguma idéia?

    
por krystah 06.01.2014 / 16:27

3 respostas

26
$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3
cucumbers

O -d ' ' diz cut para dividir em espaços. -f 3 seleciona a terceira coluna.

Você também pode usar awk , que já faz a divisão com base no espaço e disponibiliza as colunas como $1 , $2 ,…

$ echo "Watermelons and cucumbers" | awk '{ print $3 }'
cucumbers
    
por 06.01.2014 / 16:30
12

Eu provavelmente usaria uma das opções já dadas por @slhck, mas aqui estão mais algumas maneiras de fazer isso:

  1. Usando matrizes, como você faria em qualquer outro idioma:

    $ foo=( $(SayStuff) ) 
    $ echo ${foo[2]}
    cucumbers
    

    O var=() declara uma matriz, $(command) salva a saída do comando. Portanto, foo=( $(SayStuff) ) armazena a saída de SayStuff na matriz foo e, em seguida, echo é o terceiro elemento com ${foo[2]} .

  2. sed

    $ SayStuff | sed 's/.* \(.*\)//'
    cucumbers
    

    O comando sed substituirá ( s/// ) tudo pela última palavra. A regex corresponde a qualquer coisa até um espaço ( .* ), que corresponderá a tudo até o último espaço e, em seguida, captura a última palavra (\(.*\) . Como a palavra foi capturada, podemos nos referir a ela como .

    Uma versão mais simples:

    $ SayStuff | sed 's/.* //'
    cucumbers
    
  3. bash

    $ foo=$(SayStuff); echo ${foo##* } 
    cucumbers
    

    Isso usa as habilidades de manipulação de string do bash, veja aqui para mais detalhes.

  4. Mais bash

    $ SayStuff | while read a b c; do echo $c; done
    cucumbers
    
  5. Perl, onde, claro, há muitas maneiras de fazer isso:

    $ SayStuff | perl -lane 'print $F[$#F]'
    cucumber
    

    O -a faz com que perl se comporte como awk , dividindo linhas no espaço em branco e salvando no array @F . Em seguida, imprimimos o último elemento de @F ( $#F é o número de elementos em @F ). O -l diz ao perl para adicionar uma nova linha a cada instrução print , o -n que deve processar STDIN linha por linha e -e que deve executar o script fornecido na linha de comando.

    $ SayStuff | perl -pe 's/.* //'
    cucumber
    

    As opções foram explicadas acima, estamos apenas excluindo tudo até o último espaço e imprimindo ( -p ).

    $ perl -le 'print $ARGV[$#ARGV]' $(SayStuff)
    cucumbers
    

    Aqui estamos passando Watermelons and cucumbers como argumentos, o que perl salvará na matriz @ARG e, assim, imprimimos o último elemento de @ARG .

  6. truque. Este usa sed para converter espaços em novas linhas e, em seguida, tail para imprimir apenas a última linha.

    $ SayStuff | sed 's/ /\n/g' | tail -n 1
    cucumbers
    
  7. grep e expressões regulares, usando -o , que imprime apenas a string correspondente.

    $ SayStuff | grep -Po '\w+$' 
    cucumbers
    
  8. traindo

    $ SayStuff | grep -o cucumbers
    cucumbers
    
por 06.01.2014 / 16:45
2

Aqui está mais uma explicação:

Usage: cut OPTION... [FILE]...

Print selected parts of lines from each FILE to standard output.

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter

   -f, --fields=LIST
          select only these fields;  also print any line that contains  no
          delimiter character, unless the -s option is specified

Então, se você precisa do 3º campo e é delimitado por espaços, então é

$ echo "Watermelons and cucumbers" | cut -d ' ' -f 3  
cucumbers

Se você quiser o campo LAST , provavelmente deve usar awk .
Neste caso, torna-se:

$ echo "Watermelons and cucumbers" | awk '{ print $NF }'
cucumbers

Em awk NF é o número de campos na linha, então $NF significa o último campo na linha.

    
por 06.01.2014 / 16:45