Qual é a diferença entre <<
, <<<
e < <
no bash?
command-line
bash
redirect
Searene
fonte
fonte
Respostas:
Aqui documento
<<
é conhecido comohere-document
estrutura. Você deixa o programa saber qual será o texto final e, sempre que esse delimitador for visto, ele lerá todas as coisas que você deu ao programa como entrada e executará uma tarefa nele.Aqui está o que eu quero dizer:
Neste exemplo, dizemos
wc
ao programa para aguardar aEOF
string, digite cinco palavras e depois digitaEOF
para sinalizar que estamos dando entrada. Na verdade, é semelhante a correrwc
sozinho, digitando palavras e pressionandoCtrlDNo bash, eles são implementados por meio de arquivos temporários, geralmente no formato
/tmp/sh-thd.<random string>
, enquanto no painel são implementados como pipes anônimos. Isso pode ser observado através do rastreamento de chamadas do sistema com ostrace
comando Substituabash
porsh
para ver como/bin/sh
executa esse redirecionamento.Here string
<<<
é conhecido comohere-string
. Em vez de digitar texto, você fornece uma sequência de texto pré-criada para um programa. Por exemplo, com o programabc
que podemos fazerbc <<< 5*4
para obter saída para esse caso específico, não é necessário executar o bc interativamente.As strings here no bash são implementadas por meio de arquivos temporários, geralmente no formato
/tmp/sh-thd.<random string>
, que são desvinculados posteriormente, fazendo com que ocupem algum espaço de memória temporariamente, mas não apareçam na lista de/tmp
entradas do diretório, e existam efetivamente como arquivos anônimos, que ainda podem ser referenciado por meio do descritor de arquivo pelo próprio shell e esse descritor de arquivo ser herdado pelo comando e posteriormente duplicado no descritor de arquivo 0 (stdin) viadup2()
função. Isso pode ser observado viaE via rastreamento syscalls (saída reduzida para facilitar a leitura; observe como o arquivo temporário é aberto como fd 3, dados gravados nele, em seguida, é reaberto com o
O_RDONLY
sinalizador como fd 4 e depois desvinculado, depoisdup2()
para o fd 0, que é herdadocat
posteriormente. ):Opinião: potencialmente porque as strings here usam arquivos de texto temporários, é a possível razão pela qual as strings here sempre inserem uma nova linha à direita, já que o arquivo de texto por definição POSIX precisa ter linhas que terminam em caracteres de nova linha.
Substituição de Processo
Como tldp.org explica,
Portanto, na verdade, isso é semelhante ao canal stdout de um comando para o outro, por exemplo
echo foobar barfoo | wc
. Mas observe: na página de manual do bash, você verá que é indicado como<(list)
. Então, basicamente, você pode redirecionar a saída de vários comandos (!).Nota: tecnicamente quando você diz
< <
que não está se referindo a uma coisa, mas dois redirecionamentos com redirecionamento único<
e de processo de saída de<( . . .)
.Agora, o que acontece se processarmos apenas a substituição?
Como você pode ver, o shell cria um descritor temporário de arquivo para
/dev/fd/63
onde vai a saída (que, de acordo com a resposta de Gilles , é um canal anônimo). Isso significa<
que redireciona esse descritor de arquivo como entrada para um comando.Um exemplo muito simples seria fazer a substituição do processo da saída de dois comandos echo no wc:
Então, aqui fazemos o shell criar um descritor de arquivo para toda a saída que ocorre entre parênteses e redirecioná-la como entrada para
wc
. Como esperado, o wc recebe esse fluxo de dois comandos de eco, que por si só produziriam duas linhas, cada uma com uma palavra, e apropriadamente, temos 2 palavras, 2 linhas e 6 caracteres mais duas novas linhas contadas.Nota: A substituição de processo pode ser chamada de bashismo (um comando ou estrutura utilizável em shells avançados como
bash
, mas não especificado pelo POSIX), mas foi implementadaksh
antes da existência do bash como página de manual do ksh e esta resposta sugere. Cascas comotcsh
emksh
no entanto não têm substituição de processo. Então, como podemos redirecionar a saída de vários comandos para outro comando sem substituição de processo? Agrupamento e tubulação!Efetivamente, é o mesmo do exemplo acima. No entanto, isso é diferente sob a cobertura da substituição do processo, uma vez que fazemos stdout de todo o subshell e stdin
wc
vinculados ao pipe . Por outro lado, a substituição do processo faz com que um comando leia um descritor de arquivo temporário.Portanto, se podemos agrupar com tubulação, por que precisamos de substituição de processo? Porque às vezes não podemos usar tubulações. Considere o exemplo abaixo - comparando saídas de dois comandos com
diff
(que precisa de dois arquivos e, neste caso, estamos fornecendo dois descritores de arquivos)fonte
< <
é usado quando alguém está obtendo stdin de uma substituição de processo . Tal comando pode parecer:cmd1 < <(cmd2)
. Por exemplo,wc < <(date)
< <
não é uma coisa por si só, no caso de substituição de processo, é apenas um<
seguido por outra coisa que acontece no início<
<<<
foi implementado pela porta Unix do Plan 9 rc shell e depois adotado pelo zsh, bash e ksh93. Eu não chamaria isso de basismo.echo 'foo' | read; echo ${REPLY}
vai não voltarfoo
, porqueread
é iniciado em uma sub-shell - tubulação inicia uma sub-shell. No entanto,read < <(echo 'foo'); echo ${REPLY}
retorna corretamentefoo
, porque não há subcasca.< <
é um erro de sintaxe:< <()
é a substituição do processo (<()
) combinada com o redirecionamento (<
):Um exemplo artificial:
Com a substituição do processo, o caminho para o descritor de arquivo é usado como um nome de arquivo. Caso você não queira (ou não possa) usar um nome de arquivo diretamente, combine a substituição do processo com o redirecionamento.
Para ser claro, não há
< <
operador.fonte
<()
fornece uma coisa parecida com o nome do arquivo, por isso é geralmente mais útil -< <()
está substituindo o stdin onde pode não ser necessário. Emwc
, o último passa a ser mais útil. Pode ser menos útil em outro lugar< <
é um erro de sintaxe, você provavelmente quer dizercommand1 < <( command2 )
que é um redirecionamento simples de entrada seguido por uma substituição de processo e é muito semelhante, mas não equivalente a:A diferença assumindo que você está executando
bash
écommand1
executada em um subshell no segundo caso, enquanto é executada no shell atual no primeiro. Isso significa que as variáveis definidascommand1
não seriam perdidas com a variante de substituição do processo.fonte
< <
dará um erro de sintaxe. O uso adequado é o seguinte:Explicando com a ajuda de exemplos:
Exemplo para
< <()
:No exemplo acima, a entrada para o loop while virá do
ls
comando que pode ser lido linha por linha eecho
ed no loop.<()
é usado para substituição de processo. Mais informações e exemplos<()
podem ser encontrados neste link:Substituição de processo e tubulação
fonte