bash: IFS não é respeitado pelo comando read [duplicate]

0

Na página man bash do comando read :

One line is read from the standard input, or from the file descriptor fd supplied as an argument to the -u option, split into words as described above under Word Splitting, and the first word is assigned to the first name,...

Agora tentei o seguinte:

IFS=,
echo ' a b,c d'|read -n 4 x y
echo ".$x. .$y."

Eu esperava que a saída fosse

. a b. .c d.

porque devido à mudança, a divisão de palavras deve ocorrer na vírgula ao invés do espaço, mas a saída real era

.a. ..

Isso me intriga. O .a. parece que a divisão de palavras ainda é feita em espaços, mas pelo menos, y deve ser definido como b , não estando vazio.

Não posso deixar de sentir que não entendi as explicações na página man sobre o comando read .

BTW, estou usando o bash 4.4.12.

    
por user1934428 19.12.2017 / 07:50

1 resposta

4

Funciona muito bem:

$ IFS=,; echo ' a b,c d' | { read x y; declare -p x y;}
declare -- x=" a b"
declare -- y="c d"

Notas

  1. Como está em um pipeline, a instrução read está em uma subchave. As variáveis x e y são limitadas no escopo para essa subcamada. Acima, adicionamos chaves para que a instrução declare estivesse no mesmo subshell que a instrução read . Dessa forma, a saída declare mostra os valores de x e y que foram lidos.

    Se removermos as chaves, a instrução declare não estará mais na mesma sub-sela e os valores de x e y não serão preservados. Observe:

    $ x=hot; y=cold; IFS=,; echo ' a b,c d' | read -n 4 x y; declare -p x y
    declare -- x="hot"
    declare -- y="cold"
    
  2. Para evitar o limite de subshell, podemos usar uma string here:

    $ IFS=,; read x y <<<' a b,c d'; declare -p x y
    declare -- x=" a b"
    declare -- y="c d"
    

    Com uma string here, a instrução read está no shell principal e os valores de x e y não são perdidos.

  3. -n 4 limita read para 4 caracteres. Isso provavelmente não é o que você queria. Observe:

    $ IFS=,; echo ' a b,c d' | { read -n 4 x y; declare -p x y;}
    declare -- x=" a b"
    declare -- y=""
    

    Aqui, x ocupa todos os 4 caracteres (os espaços em branco contam como caracteres), não há caracteres lidos para y .

  4. Como PesaThe , também é possível atribuir variáveis de shell localmente apenas para a execução de um comando. Como as alterações no IFS podem causar efeitos colaterais indesejados nos comandos subseqüentes, é uma boa ideia aqui. Assim:

    $ IFS=, read x y <<<' a b,c d'; declare -p x y
    declare -- x=" a b"
    declare -- y="c d"
    

    Após o comando acima ser executado, IFS é retornado ao seu valor anterior.

por 19.12.2017 / 08:04

Tags