Enviar string para stdin

157

Existe uma maneira de fazer isso efetivamente no bash:

/my/bash/script < echo 'This string will be sent to stdin.'

Estou ciente de que poderia canalizar a saída do eco como este:

echo 'This string will be piped to stdin.' | /my/bash/script
Todos os trabalhadores são essenciais
fonte
1
O que você quer dizer com efetivamente , por que o cachimbo não é uma maneira de fazer isso?
Andy
Ambos os comandos que você listou devem fazer exatamente a mesma coisa. Qual problema você está tendo?
Flimzy
5
@Flimzy: afaik, o primeiro não funcionará conforme o esperado, ele tentará abrir um arquivo chamado #echo
Andy
Oh, certo. Então, o que há de errado com a segunda forma?
Flimzy
2
@Flimzy: além disso, o >formulário de redirecionamento abrirá um descritor de arquivo como fd 0(stdin), enquanto o |opens inicia um processo filho e o anexa stdout (fd 1) ao stdin do outro processo. Este facto pode ter consequências não triviais (pense sobre o compartilhamento de variáveis de ambiente?)
sehe

Respostas:

261

Você pode usar uma linha heredoc

cat <<< "This is coming from the stdin"

o acima é o mesmo que

cat <<EOF
This is coming from the stdin
EOF

ou você pode redirecionar a saída de um comando, como

diff <(ls /bin) <(ls /usr/bin)

ou você pode ler como

while read line
do
   echo =$line=
done < some_file

ou simplesmente

echo something | read param
jm666
fonte
E como inserir valores binários dessa maneira? Sem usar o tubo (eu sei que pode ser feito com o tubo como segue: echo -e "\x01\x02..." | ./script)
cprcrack
Eu gosto de escrever de outra maneira: <<< "Isso vem de stdin" perl ..., dessa forma parece com o lado esquerdo do pipe.
Pyrolistical
@Pyrolistical yes! Especialmente útil ao dominar, por exemplo, um perl oneliner a partir de uma linha de comando - edição fácil dos argumentos do perl sem a necessidade de muitos movimentos para trás com o cursor. :)
jm666
@ jm666 triste coisa é que eu aprendi ontem, se você usar uma festança apelido, basta usar os command_alias formulário <<< "string stdin", caso contrário, ele vai dizer comando não encontrado
Pyrolistical
@ jm666 Existe algum lugar em que eu possa aprender mais <<<? Tenho vergonha de admitir que nunca o vi antes e estou totalmente confuso com isso. Eu tentei pesquisar no Google por isso, mas meus resultados não têm relação.
Wpcarro
66

Você estava perto

/my/bash/script <<< 'This string will be sent to stdin.'

Para entrada multilinha, os documentos aqui são adequados:

/my/bash/script <<STDIN -o other --options
line 1
line 2
STDIN

Editar Para os comentários:

Para obter entrada binária, diga

xxd -r -p <<BINARY | iconv -f UCS-4BE -t UTF-8 | /my/bash/script
0000 79c1 0000 306f 0000 3061 0000 3093 0000 3077 0000 3093 0000 304b 0000 3093 0000 3077 0000 3093 0000 306a 0000 8a71 0000 306b 0000 30ca 0000 30f3 0000 30bb
0000 30f3 0000 30b9 0000 3092 0000 7ffb 0000 8a33 0000 3059 0000 308b 0000 3053 0000 3068 0000 304c 0000 3067 0000 304d 0000 000a
BINARY

Se você substituir catpara /my/bash/script(ou mesmo cair o último tubo), este impressões:

私はちんぷんかんぷんな話にナンセンスを翻訳することができ

Ou, se você quiser algo um pouco mais nerd:

0000000: 0000 0000 bef9 0e3c 59f8 8e3c 0a71 d63c  .......<Y..<.q.<
0000010: c6f2 0e3d 3eaa 323d 3a5e 563d 090e 7a3d  ...=>.2=:^V=..z=
0000020: 7bdc 8e3d 2aaf a03d b67e b23d c74a c43d  {..=*..=.~.=.J.=
0000030: 0513 d63d 16d7 e73d a296 f93d a8a8 053e  ...=...=...=...>
0000040: 6583 0e3e 5a5b 173e 5b30 203e 3d02 293e  e..>Z[.>[0 >=.)>
0000050: d4d0 313e f39b 3a3e 6f63 433e 1c27 4c3e  ..1>..:>ocC>.'L>
0000060: cde6 543e 59a2 5d3e 9259 663e 4d0c 6f3e  ..T>Y.]>.Yf>M.o>
0000070: 60ba 773e cf31 803e ee83 843e 78d3 883e  `.w>.1.>...>x..>
0000080: 5720 8d3e 766a 913e beb1 953e 1cf6 993e  W .>vj.>...>...>
0000090: 7a37 9e3e c275 a23e dfb0 a63e bce8 aa3e  z7.>.u.>...>...>
00000a0: 441d af3e 624e b33e 017c b73e 0ca6 bb3e  D..>bN.>.|.>...>
00000b0: 6fcc bf3e 15ef c33e e90d c83e d728 cc3e  o..>...>...>.(.>
00000c0: c93f d03e ac52 d43e 6c61 d83e f36b dc3e  .?.>.R.>la.>.k.>
00000d0: 2f72 e03e 0a74 e43e 7171 e83e 506a ec3e  /r.>.t.>qq.>Pj.>
00000e0: 945e f03e 274e f43e f738 f83e f11e fc3e  .^.>'N.>.8.>...>
00000f0: 0000 003f 09ee 013f 89d9 033f 77c2 053f  ...?...?...?w..?
0000100: caa8 073f 788c 093f 776d 0b3f be4b 0d3f  ...?x..?wm.?.K.?
0000110: 4427 0f3f 0000 113f e8d5 123f f3a8 143f  D'.?...?...?...?
0000120: 1879 163f 4e46 183f 8d10 1a3f cad7 1b3f  .y.?NF.?...?...?
0000130: fe9b 1d3f 1f5d 1f3f 241b 213f 06d6 223f  ...?.].?$.!?.."?
0000140: bb8d 243f 3a42 263f 7cf3 273f 78a1 293f  ..$?:B&?|.'?x.)?
0000150: 254c 2b3f 7bf3 2c3f 7297 2e3f 0138 303f  %L+?{.,?r..?.80?
0000160: 22d5 313f ca6e 333f                      ".1?.n3?

Quais são os senos dos primeiros 90 graus em flutuadores binários de 4 bytes

ver
fonte
E como inserir valores binários dessa maneira?
cprcrack
Eu usaria xxd -r(ou od) para filtrar o documento HERE
sehe
Você poderia explicar isso com um exemplo? Eu não consegui fazer isso.
precisa
1
veja resposta editada. O ponto é não incluem dados binários brutos em seu script, mas em vez filtrá-la através de um programa como o xxd
sehe
Qual é o objetivo de fazer: "/ my / bash / script <<< 'Esta string será enviada ao stdin.'" Quando você pode dizer diretamente: "/ my / bash / script 'Essa string será enviada ao stdin. '"?
Baiyan Huang
2

Você também pode usar readassim

echo "enter your name"
read name
echo $name
Rahul
fonte
2

Solução

Você deseja (1) criar saída stdout em um processo (como echo '…') e (2) redirecionar essa saída para entrada stdin de outro processo, mas (3) sem o uso do mecanismo bash pipe. Aqui está uma solução que corresponde às três condições:

/my/bash/script < <(echo 'This string will be sent to stdin.')

O <é redirecionamento de entrada normal para stdin. A <(…)é substituição processo de bater. Grosso modo, ele cria um /dev/fd/…arquivo com a saída do comando substituto e passa esse nome de arquivo no lugar do <(…), resultando aqui, por exemplo, em script < /dev/fd/123. Para detalhes, veja esta resposta

Comparação com outras soluções

  • Um heredoc de uma linha enviado ao stdin script <<< 'string'apenas permite enviar seqüências estáticas, não a saída de outros comandos.

  • Somente a substituição do processo, como em diff <(ls /bin) <(ls /usr/bin), não envia nada para o stdin. Em vez disso, a saída do processo é passada como o conteúdo dos arquivos criados em segundo plano, equivalente a, por exemplo diff /dev/fd/10 /dev/fd/11. Nesse comando, diffnão obtém entrada do stdin.

Casos de uso

Gosto disso, diferentemente do mecanismo de pipe, o < <(…)mecanismo permite colocar o comando em primeiro lugar e todas as entradas depois dele, como é o padrão para entrada nas opções da linha de comando.

No entanto, além da estética da linha de comando, há alguns casos em que um mecanismo de tubulação não pode ser usado. Por exemplo, quando um determinado comando deve ser fornecido como argumento para outro comando, como neste exemplo, comsshpass .

tanius
fonte
Alternativa interessante. Isso acontece de maneira diferente do POSIX <<<?
Todos os trabalhadores são essenciais
0
cat | /my/bash/script

Permite digitar várias linhas em um programa, sem que essa entrada seja salva no histórico nem visível em ps. Basta pressionar Ctrl + C quando terminar de digitar para finalizar cat.

Walf
fonte
-1

aliases podem e não podem processar stdin canalizado ...

Aqui criamos 3 linhas de saída

$ echo -e "line 1\nline 2\nline 3"
line 1
line 2
line 3

Em seguida, canalizamos a saída para stdin do comando sed para colocá-los todos em uma linha

$ echo -e "line 1\nline 2\nline 3" |  sed -e ":a;N;\$!ba ;s?\n? ?g"
line 1 line 2 line 3

Se definirmos um alias do mesmo comando sed

$ alias oline='sed -e ":a;N;\$!ba ;s?\n? ?g"'

Podemos canalizar a saída para o stdin do alias e ele se comporta exatamente da mesma maneira

$ echo -e "line 1\nline 2\nline 3" |  oline
line 1 line 2 line 3

O problema surge quando tentamos definir o alias como uma função

$ alias oline='function _oline(){ sed -e ":a;N;\$!ba ;s?\n? ?g";}_oline'

Definir o alias como uma função quebra o cano

$ echo -e "line 1\nline 2\nline 3" |  oline
>
KenB
fonte
Em primeiro lugar, isso não responde à pergunta - talvez você tenha respondido à pergunta errada? Em segundo lugar, por que você definiria uma função dentro de um alias? Você deveria apenas fazer function oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }. Em terceiro lugar, este sed seria muito mais compreensível com o awk:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
Leonardo Dagnino