cortando palavras diferentes da saída

2

Suponha que o resultado de um comando no shell do Linux seja o seguinte:

X and Y are friends

Existe alguma maneira de dividir cada uma das palavras (X, e, Y, são, amigos) ou as primeiras n palavras do resultado, para que possam ser usadas para diferentes operações?

    
por Black 13.09.2015 / 15:28

4 respostas

2

Que tal cut ?

$ phrase="X and Y are friends"
$ cut -d " " -f 1 <<< $phrase
X
$ cut -d " " -f 2 <<< $phrase
and
$ cut -d " " -f 3 <<< $phrase
Y
$ cut -d " " -f 4 <<< $phrase
are
$ cut -d " " -f 5 <<< $phrase
friends

O -d especifica o delimitador (um espaço) e o -f o número do campo (os campos são separados por delimitadores).

Coloquei a string em uma variável no exemplo acima, mas você pode canalizar a saída de um comando:

$ mycommand | cut -d " " -f 2
and    
    
por 13.09.2015 / 15:47
1

Você também pode fazer isso diretamente no shell usando read :

$ echo "X and Y are friends" | 
  while read a b c d e f
     do echo "a is '$a', b is '$b', c is '$c', d is '$d', e is '$e', f is '$f'"
  done
a is 'X', b is 'and', c is 'Y', d is 'are', e is 'friends', f is ''

O delimitador padrão é o espaço em branco, mas você pode defini-lo como algo diferente alterando a variável IFS :

$ echo "foo:bar" | while IFS=: read  a b; do echo "a is '$a', b is '$b'"; done
a is 'foo', b is 'bar'
    
por 13.09.2015 / 16:50
1

Existem duas maneiras principais de capturar a saída de um comando em um script de shell: substituição de comando e o read embutido.

A maneira simples de dividir a saída em palavras é basear-se no recurso de divisão integrado do shell e colocar a saída em uma matriz:

words=($(echo "X and Y are friends"))
echo "The ${words[5]} are ${words[1]} and ${words[3]}"

Isso funciona em shells com arrays: ksh93¹, mksh, bash, zsh. Em outros shells, você não pode armazenar uma lista de palavras, exceto nos parâmetros posicionais.

set -- $(echo "X and Y are friends")
echo "The $5 are $1 and $3"

Na verdade, cada palavra na saída é tratada como um padrão de caractere curinga e substituída pela lista de arquivos correspondentes, se houver. (Exceto em zsh, que só faz isso quando explicitamente instruído, a menos que no modo de compatibilidade sh.) Por exemplo, se uma das palavras for * , ela será substituída pela lista de arquivos no diretório atual. Para evitar isso, desative a correspondência de curingas:

set -f
words=($(echo "* and / are punctuation"))
echo "Here's some ${words[5]}: ${words[1]} and ${words[3]}"
set +f

Com read , você pode atribuir palavras individuais a uma variável cada. A parte complicada sobre read é que, uma vez que lê a entrada padrão, ela é freqüentemente usada como o lado direito em um tubo; mas na maioria das shells (exceção de ATT ksh e zsh), ambos os lados de um pipe são executados em uma subshell, então as atribuições de variáveis são perdidas fora do pipe. Você pode colocar read como parte de uma sequência de instruções.

echo "X and Y are friends" | {
  read -r first conjunction second verb complement remainder
  echo "The $complement are $first and $second"
}

Como alternativa, em ksh93, bash ou zsh, você pode passar a entrada em um substituição de processos .

read -r first conjunction second verb complement remainder <(echo "X and Y are friends")
echo "The $complement are $first and $second"

Se você quiser armazenar as palavras em uma matriz, poderá usar read -rA words em mksh, ksh93 e zsh ou read -ra words no bash, por exemplo, em bash

read -ra words <(echo "X and Y are friends")

é equivalente a

set -f; words=$((echo "X and Y are friends")); set +f

se o comando gerar uma única linha, exceto que não redefine a opção -f se estiver ativada antes.

¹ O Ksh88 possui matrizes, mas a atribuição usa uma sintaxe diferente.

    
por 14.09.2015 / 01:10
0

com zsh :

upToFirst5words=(${$(my-cmd)[1,5]})

Assumindo o padrão, o valor padrão do IFS, que será dividido em espaços em branco de sequências (espaço, tabulação, nova linha) ou NULs.

Você pode fazer isso:

argv=(${$(my-cmd)[1,5]})

Para essas 5 palavras estarem em $1 , $2 ... $5 .

    
por 13.09.2015 / 18:10