Qual é a diferença entre e no bash?

66

Qual é a diferença entre << , <<< e < < no bash?

    
por Searene 27.09.2015 / 09:42

4 respostas

73

Aqui documento

<< é conhecido como here-document structure. Você deixa o programa saber qual será o texto final, e sempre que esse delimitador é visto, o programa lerá todas as coisas que você deu ao programa como entrada e executará uma tarefa sobre ele.

Veja o que quero dizer:

$ wc << EOF
> one two three
> four five
> EOF
 2  5 24

Neste exemplo, dizemos a wc program para esperar por EOF string, digite cinco palavras e, em seguida, digite EOF para sinalizar que terminamos dando entrada. De fato, é semelhante a executar wc , digitando as palavras e pressionando Ctrl D

Aqui string

<<< é conhecido como here-string . Em vez de digitar texto, você fornece uma string de texto pré-criada para um programa. Por exemplo, com um programa como bc , podemos fazer bc <<< 5*4 para obter a saída para esse caso específico, sem necessidade de executar bc interativamente.

Substituição de processos

Como tldp.org explica,

  

A substituição de processos alimenta a saída de um processo (ou processos) em   o stdin de outro processo.

Portanto, de fato, isso é semelhante à canalização stdout de um comando para o outro, por exemplo, echo foobar barfoo | wc . Mas observe: na bash manpage você verá que é denotado como <(list) . Então, basicamente, você pode redirecionar a saída de vários comandos (!).

Observação: tecnicamente quando você diz < < não está se referindo a uma coisa, mas dois redirecionamentos com < único e redirecionamento de processo de saída de <( . . .) .

Agora, o que acontece se apenas processarmos a substituição?

$ echo <(echo bar)
/dev/fd/63

Como você pode ver, o shell cria um descritor de arquivo temporário /dev/fd/63 para onde a saída vai. Isso significa que < redireciona esse descritor de arquivo como entrada para um comando.

Um exemplo muito simples seria fazer a substituição do processo de saída de dois comandos de echo em wc:

$ wc < <(echo bar;echo foo)
      2       2       8

Então, aqui fazemos o shell criar um descritor de arquivo para toda a saída que acontece nos parênteses e redirecionar como entrada para wc . Como esperado, wc recebe esse fluxo de dois comandos de eco, que por si só produziria duas linhas , cada um com uma palavra e, apropriadamente, temos 2 palavras, 2 linhas e 6 caracteres, mais duas novas linhas contadas.

Nota: A substituição do processo pode ser chamada de bashism (um comando ou estrutura utilizável em shells avançados como bash , mas não especificado pelo POSIX), mas foi implementado em ksh antes da existência do bash como página do manual do ksh e esta resposta sugere. No entanto, shells como tcsh e mksh não possuem substituição de processo. Então, como poderíamos sair por aí redirecionando a saída de múltiplos comandos para outro comando sem a substituição do processo? Agrupamento mais tubulação!

$ (echo foo;echo bar) | wc
      2       2       8

Efetivamente isto é o mesmo que o exemplo acima, No entanto, isso é diferente sob o capô da substituição de processo, já que fazemos stdout dos comandos agrupados e stdin de wc vinculado ao pipe . Por outro lado, a substituição do processo faz com que um comando leia um descritor de arquivo temporário.

Então, se podemos fazer o agrupamento com tubulação, por que precisamos de substituição de processo? Porque às vezes não podemos usar tubulação. Considere o exemplo abaixo - comparando as saídas de dois comandos com diff (que precisa de dois arquivos e, neste caso, estamos dando a ele dois descritores de arquivo)

diff <(ls /bin) <(ls /usr/bin)
    
por Sergiy Kolodyazhnyy 27.09.2015 / 09:56
22

< < é um erro de sintaxe:

$ cat < <
bash: syntax error near unexpected token '<'

< <() é substituição de processo ( <() ) combinada com redirecionamento ( < ):

Um exemplo inventado:

$ wc -l < <(grep ntfs /etc/fstab)
4
$ wc -l <(grep ntfs /etc/fstab)
4 /dev/fd/63

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 diretamente um nome de arquivo, você combina a substituição do processo com o redirecionamento.

Para ser claro, não há operador < < .

    
por muru 27.09.2015 / 10:05
10

< < é um erro de sintaxe, você provavelmente quer dizer command1 < <( command2 ) , que é um redirecionamento de entrada simples seguido por uma substituição de processo e é muito semelhante mas não equivalente a:

command2 | command1

A diferença assumindo que você está executando bash é command1 é executada em um subshell no segundo caso enquanto ele é executado no shell atual no primeiro. Isso significa que as variáveis configuradas em command1 não seriam perdidas com a variante de substituição do processo.

    
por jlliagre 27.09.2015 / 10:09
8

< < fornecerá um erro de sintaxe. O uso adequado é o seguinte:

Explicando com a ajuda dos exemplos:

Exemplo para < <() :

while read line;do
   echo $line
done< <(ls)

No exemplo acima, a entrada para o loop while virá do comando ls , que pode ser lido linha por linha e echo ed no loop.

<() é usado para substituição de processo. Mais informações e exemplos para <() podem ser encontrados neste link:

Substituição de processo e pipe

    
por snoop 27.09.2015 / 10:06