Como esperar que o programa termine e canalize stdin para stdout quando estiver pronto?

1

Estou tentando descobrir como esperar que um comando seja concluído e, em seguida, canalize stdin para stdout. Eu estou em um mac, mas acho que a minha pergunta é mais sobre como esperar por um processo para concluir e canalizar a saída, então, qualquer coisa a ver com um mac.

Tenho notado que no mac, posso executar alguns comandos say juntos, e eles esperam que cada frase seja totalmente falada antes de iniciar a próxima, se eu usar o operador && para se juntar a eles para cima.

$ say "stage 1" && say "stage 2"

Aqui é onde o caso de uso real é - Eu tenho um script bash que eu gostaria que ele passasse stdin para stdout, após ele terminar de dizer algo.

$ cat /etc/passwd | say_and_pass "stage 1" | grep -v test | say "stage 2"

Então, conceitualmente, isso diria em voz alta, "estágio 1", em seguida, dizer imediatamente "estágio 2" e, em seguida, despejar o conteúdo de grepped de /etc/password para stdout.

Meu crack inicial no script say_and_pass é este:

say_and_pass

#!/usr/bin/env bash
OUT="$*"
say "$OUT" && cat 

Mas parece que não funciona ;-)

    
por Brad Parks 13.04.2018 / 17:10

4 respostas

0

Acontece que tudo que eu tive que fazer foi consumir todos os stdin no início do meu script ... Eu não quero que ele processe stdin como ele é recebido, mas quando todo o comando anterior na cadeia de pipe terminar. / p>

Então, meu script say_and_pass é simplesmente isso, que funciona para o meu caso de uso!

#!/usr/bin/env bash

OUT=$(cat -)

MSG="$*"
say "$MSG"

echo "$OUT"
    
por 13.04.2018 / 21:42
1

Here's where the real use case is - I've got a bash script that I'd like to have it just pass stdin to stdout, after it finishes saying something.

$ cat /etc/password | say_and_pass "stage 1" | grep -v test | say "stage 2"

O problema com o que você está tentando fazer aqui é que você parece ter dois fluxos de dados - um para say e um para processamento de texto (ou seja, cat e grep ).

Você não pode usar um único pipeline para isso, pois apenas misturará os dados. cat /etc/passwd | say fará seu computador tentar falar todo o conteúdo do arquivo. Além disso, say não grava qualquer coisa na saída padrão, então nada iria mais longe no pipeline.

Se você quiser "interromper" seu fluxo de processamento de dados para manipular saída separada para outros utilitários como say , será necessário configurar um FIFO (ou seja, um "canal nomeado") para um ou outro de seus fluxos de dados ou usar arquivos temporários gravados no disco.

Seu caso de uso demonstrativo não é muito útil para um exemplo, pois apesar do say s, você está apenas grep ping em um arquivo, o que pode ser feito em uma etapa com grep -v test /etc/passwd ( cat file | grep pattern é um uso inútil de cat ).

Tudo o que foi dito, um exemplo usando um arquivo de rascunho:

scratch=$(mktemp)
trap "rm -f $scratch" EXIT
cat /etc/passwd > $scratch
say "Stage one"
grep -v test $scratch
say "Stage two"

E um usou um pipe nomeado para say :

mkfifo youtalktoomuch
say youtalktoomuch &
exec 3> youtalktoomuch
do_thing_one
echo "Stage one" > youtalktoomuch
do_thing_two
echo "Stage two" > youtalktoomuch
exec 3>&-
rm youtalktoomuch

Once again, though, if you need to connect the output of 'do_thing_one' to the input of 'do_thing_two' without piping one into the other, you will need to use either another named pipe or a scratch file on disk to hold the data.
    
por 13.04.2018 / 17:48
0

Tente:

say "stage 1" && cat /etc/passwd  |  { say "stage 2" && grep -v test ; }

Na verdade, não tenho say no meu sistema, mas isso funciona:

espeak "stage 1" && cat /etc/passwd  |  { espeak "stage 2" && grep -v test ; }
    
por 13.04.2018 / 21:51
-3
#!/usr/bin/env bash
OUT="$*"
say "$OUT" | cat -

Se você usar & &; seu significado, faça o comando fisrt after do segundo comando, mas o resultado do comando fisrt não é importante para o segundo comando. Quer dizer, você tem 2 comandos diferentes, porque você usa & & Se você usa |, significa que o comando fisrt faz alguma coisa e dá algo para o segundo comando. O final, você deve dar um atributo para o comando cat. Desculpe meu inglês pelo jeito

    
por 13.04.2018 / 17:39

Tags