Por que não posso canalizar entrada para o comando 'read' no Bash, no Cygwin, usando o ConEmu, no Windows?

0

Estou tentando armazenar a saída de um pipe em uma variável.

Depois de ler este post ( Acessando a saída de um Bash pipe com 'read' ), eu tive algumas dúvidas lembrando se eu tive sucesso em fazer isso, em um sistema Unix.

Então eu encontrei este post ( Como fazer um loop através de nomes de arquivos retornados por find? ), e foi lembrado de que funciona, às vezes usando read -r <varname> também.

Ambiente:

User@Computer /cygdrive/...
$ echo $SHELL
/bin/bash

User@Computer /cygdrive/...
$ echo $BASH_VERSION
4.4.5(1)-release

User@Computer /cygdrive/...
$ uname -a
CYGWIN_NT-10.0 Computer 2.6.1(0.305/5/3) 2016-12-16 11:55 x86_64 

User@Computer /cygdrive/...
$ read --help
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
    Read a line from the standard input and split it into fields.

Tentativas:

User@Computer /cygdrive/...
$ echo $var


User@Computer /cygdrive/...
$ echo "hi" | read var

User@Computer /cygdrive/...
$ echo $var


User@Computer /cygdrive/...
$ echo "hi" | read -r var

User@Computer /cygdrive/...
$ echo $var

User@Computer /cygdrive/...
$ read var
hi

User@Computer /cygdrive/...
$ echo $var
hi

User@Computer /cygdrive/...
$ echo "hi" | cat
hi

User@Computer /cygdrive/...
$ echo -e '1\n2\n3\n' | xargs
1 2 3

Eu também tentei isso no próprio processo e janela do bash.exe :

User@Computer /cygdrive/...
$ echo "hi" | read var;echo $var;

Também fazendo o mesmo no "Bash no Ubuntu no Windows" bash.exe :

echo "hi" | read var;echo $var;

Ainda não há resultado bem-sucedido da tarefa. Estou ciente de que posso contornar esse método, provavelmente usando $() ou as setas de redirecionamento.

Existe uma maneira de fazer isso usando este método de comando read line no Windows?

Atualizar

Para algumas das respostas, eu sabia que algumas postariam alternativas como $() . É por isso que eu já mencionei esse método intencionalmente, incluindo um link no qual vários já estavam listados, além de perguntar especificamente se havia uma maneira de usar o utilitário read line para armazenar entradas em uma variável, não usando redirecionamento, mas sim canalizando dados através de uma cadeia de comando, como eu tinha feito antes em outros sistemas, mas desta vez no Windows.

    
por Pysis 02.08.2017 / 03:14

3 respostas

0

Você pode usar o pipe nomeado.

Exemplo:

sharuzzaman@laptop /cygdrive/...
$ mkfifo mypipe

sharuzzaman@laptop /cygdrive/...
$ echo "hi" > mypipe &
[1] 5260

sharuzzaman@laptop /cygdrive/...
$ read asdf < mypipe

sharuzzaman@laptop /cygdrive/...
$ echo $asdf
hi
[1]+  Done                    echo "hi" > mypipe
    
por 02.08.2017 / 05:12
0

Para resultados de linha única, a maneira canônica de fazer isso no bash é:

variable=$(the_command the_command_args)

por exemplo:

today=$(date +%Y%m%d) 

(e os argumentos do comando podem conter $ -variables, se necessário).

Para resultados com várias minas, você usa um loop para processar cada linha por vez:

for f in $(ls -1)
do
    echo @@@@"$f"
done
    
por 02.08.2017 / 10:54
0

Para as outras respostas, elas parecem abordagens interessantes com bons exemplos, mas eu estava realmente curioso para saber por que essa abordagem que eu vinha usando ad-hoc e em alguns scripts de shell 'parou' de funcionar ou não funcionou no meu sistema Windows.

Eu não vi que eles postaram respostas diretamente relacionadas a como eu posso conseguir isso usando read e pipes, então aqui está minha atualização como uma forma de fechamento onde eu testo alguns exemplos e realço a funcionalidade específica que tem foi aludido.

Bem, para os comentários sobre a questão, eu posso mostrar isso funciona no meu sistema Mac (10.12.5), no iTerm 3.0.15, no fish shell:

⋊> ~ echo "hi" | read var;echo $var;
hi
⋊> ~ fish -v
fish, version 2.6.0

Quando eles fazem referência a um subshell sendo usado, ele parece funcionar em fish , o que eu entendo tem um padrão de arquitetura e design diferente, embora em algumas partes eu esperaria camadas de funcionamento semelhante, pelo menos do ponto de vista do caso de uso .

Então tentei a abordagem novamente no meu Mac, em ambos os intérpretes.

Em fish :

⋊> ~ echo -ne '1\n2\n3\n' | while read line; echo "a$line""a"; end
a1a
a2a
a3a

Em bash :

bash-3.2$ echo -ne '1\n2\n3\n' | while read line; do echo "a$line""a"; done
a1a
a2a
a3a

bash-3.2$ echo $BASH
/bin/bash
bash-3.2$ echo $BASH_VERSION
3.2.57(1)-release

Toda a funcionalidade parece estar (principalmente) funcionando como esperado aqui. Fiquei um pouco surpreso ao descobrir que a variável não está gerando em bash , mas meu problema original que pensei veio de não obter dados esperados para persistir nesse loop. Vou ter que verificar meu código mais de perto com tudo isso em mente novamente.

Resultado final

O ponto principal que está sendo destacado aqui não é armazenar a entrada padrão em variáveis simples, canalizando em bash e continuando normalmente em um script, já que ele é executado em uma subcamada, de acordo com Sharuzzaman Ahmat Raslan e dave_thompson_085 .

Em vez disso, funciona dessa maneira em fish , ou posso ter mais cuidado trabalhando diretamente na cadeia de tubos com o loop while e voltar para verificar meu código para esses problemas.

Outras Notas

Acho que outro problema em uma das linhas de código é que eu estava tentando usar read -r <varname> , mas acabei digitando read -p <varname> . O último consome um argumento extra para formar um prompt para o comando de leitura, e no meu exemplo com apenas 1 argumento, não deixa nenhum nome de variável útil para armazenar informações e recuperar a partir dele. O primeiro às vezes é útil nos exemplos de outros quando não quer usar seqüências de escape de retrocesso, sempre que for. Portanto, evite erros como este!

    
por 02.08.2017 / 21:00