Para o redirecionamento de entrada, existem diferenças funcionais entre o bash / zsh “$ (file)” e o arquivo tradicional?

2

Estou perguntando apenas sobre o uso que teria o mesmo efeito que o redirecionamento de entrada tradicional de um arquivo.

<<<"$(<file)"

até onde eu sei, é equivalente a

<file

Parece-me que estes são funcionalmente equivalentes. No nível baixo, parece que o < < < aqui o documento pode realmente causar mais cópias dos dados na memória de uma só vez.

Eu sei que esse tipo de redirecionamento existe tanto no bash quanto no zsh, mas não estou familiarizado com o modo como ele é implementado, embora eu veja as páginas de manual do zsh contenham alguns detalhes de implementação.

    
por RobertL 30.10.2015 / 13:38

2 respostas

4

Em <<<"$(<file)" (suportado por zsh (onde <<< foi introduzido pela primeira vez, inspirado pelo mesmo operador na porta Unix de rc ), ksh93 (o operador $(<file) foi introduzido por ksh ), mksh e bash ),

Para $(<file) , o shell lê o conteúdo de file (engasga em bytes NUL, exceto zsh ), remove todos os caracteres de nova linha e faz a expansão de $(<file) (portanto, o conteúdo de o arquivo é armazenado como um todo na memória).

Para <<< some-text , o shell armazena some-text seguido por um caractere de nova linha em um arquivo temporário e abre esse arquivo temporário no descritor de arquivo 0.

Então, basicamente <<<"$(<file)" abre o stdin para leitura em uma cópia temporária de file , em que caracteres de nova linha foram substituídos por apenas um (e com vários desvios se o arquivo contiver bytes NUL, exceto zsh ). / p>

Enquanto em < file , é file que é aberto diretamente para leitura em stdin.

É claro que < file é muito mais eficiente (não envolve uma cópia no disco e na memória), mas pode-se querer usar o <<<"$(<file)" para garantir que o arquivo aberto no stdin seja um regular , ou para garantir que o arquivo foi totalmente lido no momento em que o comando é iniciado (caso esse comando grave nele) ou outro redirecionamento for processado (como um que truncará file como em tr 1 2 <<< "$(<file)" > file ).

Observe que yash suporta o operador <<< (embora o implemente com um pipe (portanto, não um arquivo regular ) em vez de um arquivo temporário). mas não o $(<file) one. Você pode usar <<<"$(cat < file)" em vez disso. yash strings são apenas caracteres, então o "$(cat < file)" irá se engasgar com sequências de bytes que não formam caracteres válidos, enquanto outros shells normalmente podem lidar com eles.

    
por 02.11.2015 / 18:54
2

Todos esses comandos gravarão o conteúdo (txt) (não tente isso sobre arquivos binários) de um arquivo:

cat        file
cat       <file
echo   "$(<file)"
cat <<<"$(<file)"

Mas isso é porque o gato é um comando muito adaptável, não porque os comandos são iguais.

  1. O comando cat file imprime o conteúdo do arquivo, cat neste caso está atuando sobre um arquivo real. É semelhante a less file . Mas menos é muito mais rigoroso, ele precisa de um arquivo real.

  2. O comando cat <file está fornecendo o conteúdo do arquivo (já extraído como um fluxo) para cat, cat está recebendo um fluxo da entrada padrão. Mas o gato não tem problemas com isso, ele também imprime o fluxo e vemos o mesmo resultado.

  3. Nesse caso echo "$(<file)" , o "$(< file)" é exatamente igual (exceto para alguns detalhes do sub-shell) para "$(cat file)" . Isso significa que o comando cat é executado. Em seguida, sua saída é convertida em uma cadeia de texto pela execução do comando $(...) e, finalmente, essa sequência de texto é impressa por eco. Nós vemos o conteúdo do arquivo novamente.

  4. O comando cat <<<"$(<file)" segue esta sequência:

    • "$(<file)" arquivo é lido e enviado como uma string

    • o <<< envia a string para a entrada padrão (stdin)

    • e cat imprime o que recebe em sua entrada (stdin).

Nós vemos o mesmo conteúdo do arquivo.

Conclusão

Nós vemos a mesma saída em todos os casos. Mas o conteúdo do arquivo muda em "o que eles são" (nome do arquivo, fluxo, string, etc.) em cada parte dos comandos.

    
por 30.10.2015 / 16:35