Estou tentando obter bash para processar dados de stdin que é canalizado, mas sem sorte. O que quero dizer é que nenhum dos seguintes trabalhos:
echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=
echo "hello world" | read test; echo test=$test
test=
echo "hello world" | test=`cat`; echo test=$test
test=
onde eu quero que a saída esteja test=hello world
. Eu tentei colocar "" aspas "$test"
que também não funcionam.
shopt -s lastpipe
- tldp.org/LDP/abs/html/bashver4.html#LASTPIPEOPTRespostas:
Usar
Você pode enganar
read
a aceitação de um pipe como este:ou mesmo escrever uma função como esta:
Mas não faz sentido - suas atribuições de variáveis podem não durar! Um pipeline pode gerar um subshell, onde o ambiente é herdado por valor, não por referência. Isso é por que
read
isso não se incomoda com a entrada de um tubo - é indefinido.FYI, http://www.etalabs.net/sh_tricks.html é uma coleção bacana do lixo necessário para combater as esquisitices e incompatibilidades das cascas de bourne, sh.
fonte
test=`echo "hello world" | { read test; echo $test; }`
{}
vez de()
agrupar esses dois comandos?read
entrada do pipe, mas em usar a variável no mesmo shell que executa oread
.bash permission denied
ao tentar usar esta solução. Meu caso é bastante diferente, mas eu não poderia encontrar uma resposta para isso em qualquer lugar, o que funcionou para mim foi (um exemplo diferente mas o uso similar):pip install -U echo $(ls -t *.py | head -1)
. No caso, alguém já teve um problema semelhante e se deparou com essa resposta como eu.se você quiser ler muitos dados e trabalhar em cada linha separadamente, poderá usar algo como isto:
se você quiser dividir as linhas em várias palavras, poderá usar várias variáveis no lugar de x, assim:
alternativamente:
Mas assim que você começar a querer fazer algo realmente inteligente com esse tipo de coisa, é melhor usar uma linguagem de script como o perl, onde você pode tentar algo assim:
Há uma curva de aprendizado bastante íngreme com o perl (ou eu acho que qualquer uma dessas linguagens), mas você achará muito mais fácil a longo prazo se quiser fazer qualquer coisa, exceto o mais simples dos scripts. Eu recomendaria o Perl Cookbook e, é claro, a linguagem de programação Perl de Larry Wall et al.
fonte
read
não lê de um tubo (ou possivelmente o resultado é perdido porque o tubo cria um subshell). No entanto, você pode usar uma string here no Bash:Mas consulte a resposta do @ chepner para obter informações sobre
lastpipe
.fonte
Essa é outra opção
fonte
<(..)
resta$(..)
é que<(..)
retorna cada linha ao chamador assim que o comando que ele executa o disponibiliza.$(..)
, no entanto, aguarda o comando concluir e gerar toda sua saída antes de disponibilizar qualquer saída para o chamador.Não sou especialista em Bash, mas me pergunto por que isso não foi proposto:
Prova única de que funciona para mim:
fonte
bash
4.2 introduz alastpipe
opção, que permite que seu código funcione como gravado, executando o último comando em um pipeline no shell atual, em vez de em um subshell.fonte
A sintaxe de um canal implícito de um comando shell para uma variável bash é
ou
Nos seus exemplos, você está canalizando dados para uma declaração de atribuição, que não espera nenhuma entrada.
fonte
A primeira tentativa foi bem próxima. Essa variação deve funcionar:
e a saída é:
Você precisa de chaves após o tubo para incluir a tarefa a ser testada e o eco.
Sem os chavetas, a tarefa a ser testada (após o pipe) está em um shell, e o eco "test = $ test" está em um shell separado que não conhece essa tarefa. É por isso que você estava recebendo "test =" na saída em vez de "test = hello world".
fonte
A meu ver, a melhor maneira de ler o stdin no bash é a seguinte, que também permite trabalhar nas linhas antes que a entrada termine:
fonte
Porque eu me apaixono por isso, gostaria de deixar uma nota. Encontrei este tópico, porque tenho que reescrever um script sh antigo para ser compatível com POSIX. Isso basicamente significa contornar o problema de pipe / subshell introduzido pelo POSIX, reescrevendo o código da seguinte maneira:
para dentro:
E código como este:
para dentro:
Mas o último não se comporta da mesma maneira na entrada vazia. Com a notação antiga, o loop while não é inserido na entrada vazia, mas na notação POSIX, é! Eu acho que é devido à nova linha antes do EOF, que não pode ser omitida. O código POSIX que se comporta mais como a notação antiga é assim:
Na maioria dos casos, isso deve ser bom o suficiente. Infelizmente, isso ainda não se comporta exatamente como a notação antiga, se some_comand imprime uma linha vazia. Na notação antiga, o corpo while é executado e na notação POSIX, quebramos na frente do corpo.
Uma abordagem para corrigir isso pode ser assim:
fonte
Um script inteligente que pode ler dados do PIPE e dos argumentos da linha de comando:
Resultado:
Explicação: Quando um script recebe dados por canal, o stdin / proc / self / fd / 0 será um link simbólico para um canal.
Caso contrário, ele apontará para o terminal atual:
A
[[ -p
opção bash pode verificar se é um tubo ou não.cat -
lê o destdin
.Se usarmos
cat -
quando não houverstdin
, ele esperará para sempre, é por isso que o colocamos dentro daif
condição.fonte
/dev/stdin
que é um link para/proc/self/fd/0
Introduzir algo em uma expressão que envolva uma tarefa não se comporta assim.
Em vez disso, tente:
fonte
O código a seguir:
funcionará também, mas abrirá outra nova subcamada após o tubo, onde
não vai.
Eu tive que desativar o controle de tarefas para fazer uso do método chepnars (eu estava executando este comando no terminal):
O Bash Manual diz :
Nota: o controle da tarefa é desativado por padrão em um shell não interativo e, portanto, você não precisa do
set +m
script interno.fonte
Eu acho que você estava tentando escrever um script de shell que poderia receber informações do stdin. mas enquanto você tenta fazê-lo em linha, você se perde tentando criar essa variável test =. Eu acho que não faz muito sentido fazê-lo em linha, e é por isso que não funciona da maneira que você espera.
Eu estava tentando reduzir
para obter uma linha específica de várias entradas. para que eu pudesse digitar ...
então eu preciso de um pequeno programa shell capaz de ler a partir de stdin. como você faz.
ai está.
fonte
Que tal agora:
fonte