ler -r vs ler linha -r e IFS

1

Eu tenho revisado o material do IFS por aqui e ali e não posso explicar o comportamento de trechos de código diferentes que se resumem a isso:

$ read -r < <(printf "%s\n" " x ")  && echo \<"$REPLY"\>
< x >
$ read -r line < <(printf "%s\n" " x ")  && echo \<"$line"\>
<x>

É claro que man bash tem tudo.

If no names are supplied, the line read is assigned to the variable REPLY. The return code is zero, unless end-of-file is encountered, read times out (in which case the return code is greater than 128), a variable assignment error (such as assigning to a readonly variable) occurs, or an invalid file descriptor is supplied as the argument to -u.

Eu apenas pensei que seria bom se uma dessas respostas relacionadas a IFS contivesse uma palavra sobre este casus . Alguns estão mesmo abertamente errados, como se vê. Um exemplo é a edição neste parágrafo de esta resposta :

IFS is not used by read unless it is called with arguments. (Edit: This is not exactly true: whitespace characters, i.e. space and tab, present in IFS are always ignored at the beginning/end of the input line. )

Esta é uma pergunta retórica sem ponto de interrogação. Mas corrija-me se estiver errado, etc.

    
por Tomasz 31.07.2017 / 19:11

1 resposta

2

O comportamento normal, seguido por todas as shells Bourne / POSIX (traço, ksh, pdksh, mksh, bash, zsh, mesmo quando não estão no modo sh emulation, BusyBox sh, Bourne shell,…) é que read -r line strips leading and caracteres de espaço em branco à direita. Mais geralmente, read -r line retira um separador principal que consiste em um número arbitrário de caracteres em branco a partir de IFS e no máximo um caractere que não seja espaço em branco de IFS . No final da linha, somente os espaços em branco podem ser removidos, porque se a linha terminar com um caractere separador que não seja espaço em branco, ela terminará com um campo vazio. Este é um caso especial do caso mais geral: a primeira variável obtém o primeiro campo, a segunda variável obtém o segundo campo, etc., e se houver mais campos que variáveis, as últimas variáveis obtêm o restante da linha, exceto o espaço em branco à direita.

Chamar read com um nome de variável implícito é uma extensão ksh que bash e zsh imitate. Em ksh (ATT e pdksh / mksh) e em zsh, read sem um nome de variável é exatamente equivalente a read com o nome da variável REPLY . No bash, por algum motivo, o comportamento é diferente: quando o nome da variável é implícito, IFS strippping de espaços em branco não é feito. Isso é deliberado, mas o raciocínio para torná-lo diferente me escapa. (Se você não quiser decapagem, o método padrão é executar IFS= read -r .)

  /* If there are no variables, save the text of the line read to the
     variable $REPLY.  ksh93 strips leading and trailing IFS whitespace,
     so that 'read x ; echo "$x"' and 'read ; echo "$REPLY"' behave the
     same way, but I believe that the difference in behaviors is useful
     enough to not do it.  Without the bash behavior, there is no way
     to read a line completely without interpretation or modification
     unless you mess with $IFS (e.g., setting it to the empty string).
     If you disagree, change the occurrences of '#if 0' to '#if 1' below. */
  if (list == 0)
    {
#if 0
      orig_input_string = input_string;
      for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t
        ;
      input_string = t;
      input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw
#endif
    
por 03.08.2017 / 02:47

Tags