$(<file)(também trabalha com `<file`) é um operador especial do shell Korn copiado por zshe bash. Parece muito com substituição de comando, mas na verdade não é.
Nos shells POSIX, um comando simples é:
< file var1=value1 > file2 cmd 2> file3 args 3> file4
Todas as peças são opcionais, você pode ter apenas redirecionamentos, apenas comandos, apenas atribuições ou combinações.
Se houver redirecionamentos, mas nenhum comando, os redirecionamentos serão executados (para que um > fileabra e trunque file), mas nada acontece. assim
< file
Abre filepara leitura, mas nada acontece, pois não há comando. Então o fileé então fechado e é isso. Se $(< file)fosse uma simples substituição de comando , ela se expandiria para nada.
Na especificação POSIX , em $(script), se scriptconsiste apenas em redirecionamentos, produz resultados não especificados . Isso é para permitir esse comportamento especial do shell Korn.
No ksh (testado aqui com ksh93u+), se o script consistir em um e apenas um comando simples (embora os comentários sejam permitidos antes e depois) que consistem apenas em redirecionamentos (sem comando, sem atribuição) e se o primeiro redirecionamento for um stdin (fd 0) única entrada ( <, <<ou <<<) de redireccionamento, de modo que:
$(< file)
$(0< file)
$(<&3)(também $(0>&3), na verdade, o mesmo operador)
$(< file > foo 2> $(whatever))
mas não:
$(> foo < file)
- nem
$(0<> file)
- nem
$(< file; sleep 1)
- nem
$(< file; < file2)
então
- todos, exceto o primeiro redirecionamento, são ignorados (são analisados)
- e ele se expande para o conteúdo do arquivo / heredoc / herestring (ou qualquer outro conteúdo que possa ser lido no descritor de arquivo, se estiver usando coisas do tipo
<&3), menos os caracteres de nova linha à direita.
como se estivesse usando, $(cat < file)exceto que
- a leitura é feita internamente pela casca e não por
cat
- nenhum tubo ou processo extra está envolvido
- Como conseqüência do exposto acima, como o código interno não é executado em um subshell, qualquer modificação permanece posteriormente (como em
$(<${file=foo.txt})ou $(<file$((++n))))
- erros de leitura (embora não sejam erros ao abrir arquivos ou duplicar descritores de arquivos) são ignorados silenciosamente.
Em zsh, é o mesmo, exceto que esse comportamento especial só é acionado quando há apenas um redirecionamento de entrada de arquivo ( <fileou 0< file, não <&3, <<<here, < a < b...)
No entanto, exceto ao emular outras conchas, em:
< file
<&3
<<< here...
é quando há apenas redirecionamentos de entrada sem comandos, fora da substituição de comando, zshexecuta o $READNULLCMD(um pager por padrão) e quando há redirecionamentos de entrada e saída, o $NULLCMD( catpor padrão), portanto, mesmo que $(<&3)não seja reconhecido como especial operador, ele ainda funcionará como se kshestivesse chamando um pager para fazê-lo (esse pager agindo como se catseu stdout fosse um canal).
No entanto, enquanto ksh's $(< a < b)se expandiria para o conteúdo a, em zsh, ele se expande para o conteúdo do ae b(ou apenas bse a multiosopção for desativada), $(< a > b)iria copiar apara be expandir a nada, etc.
bash tem um operador semelhante, mas com algumas diferenças:
comentários são permitidos antes, mas não depois:
echo "$(
# getting the content of file
< file)"
funciona mas:
echo "$(< file
# getting the content of file
)"
expande para nada.
como em zsh, apenas um arquivo stdin redirecionamento, embora não há nenhuma volta queda a um $READNULLCMD, por isso $(<&3), $(< a < b)não executar os redirecionamentos mas expandir para nada.
- por algum motivo, embora
bashnão seja invocado cat, ele ainda bifurca um processo que alimenta o conteúdo do arquivo através de um canal, tornando-o muito menos otimizador do que em outros shells. É como um local $(cat < file)onde catseria construído cat.
- Como conseqüência do exposto acima, qualquer alteração feita no interior é perdida posteriormente (no
$(<${file=foo.txt})mencionado acima, por exemplo, essa $fileatribuição é perdida posteriormente).
Em bash, IFS= read -rd '' var < file (também funciona zsh) é uma maneira mais eficaz de ler o conteúdo de um arquivo de texto em uma variável. Ele também tem o benefício de preservar os caracteres de nova linha à direita. Veja também $mapfile[file]em zsh(no zsh/mapfilemódulo e apenas para arquivos regulares) que também funciona com arquivos binários.
Observe que as variantes baseadas em pdksh kshtêm algumas variações em comparação com o ksh93. De interesse, em mksh(uma dessas conchas derivadas de pdksh), em
var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)
é otimizado, pois o conteúdo do documento here (sem os caracteres finais) é expandido sem que um arquivo ou canal temporário seja usado, como é o caso dos documentos here, o que o torna uma sintaxe eficaz de cotação de várias linhas.
Ser portátil para todas as versões de ksh, zshe bash, o melhor é limitar-se a $(<file)evitar comentários e ter em mente que as modificações nas variáveis feitas dentro podem ou não ser preservadas.
bashinterpretará isso comocat filename", você quer dizer que esse comportamento é específico para comandar a substituição? Porque, se eu correr< filenamesozinho, o bash não dá certo. Ele não produzirá nada e retornará a um prompt.