文字列をstdinに送信する


157

これをbashで効果的に行う方法はありますか?

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

次のようなエコーからの出力をパイプ処理できることを知っています。

echo 'This string will be piped to stdin.' | /my/bash/script

1
効果的にどういう意味ですか、なぜこれを行う方法をパイプしないのですか?
アンディ

リストしたこれらのコマンドはどちらも、まったく同じことを行う必要があります。どんな問題がありますか
Flimzy

5
@Flimzyは:予想通り、私の知る限り、最初のものは、それが呼ばれるファイルを開こうよ、動作しませんecho
アンディ

そうそう。では、2番目のフォームの何が問題になっていますか?
Flimzy

2
@Flimzy:さらに、>リダイレクトフォームはファイル記述子をfd 0(stdin)として|開きますが、 opens は子プロセス開始し、その stdout(fd 1)を他のプロセスのstdinにアタッチします。この事実は重要な結果をもたらす可能性があります(環境変数の共有について考えてみてください)
sehe

回答:


261

あなたは一行を使うことができます heredoc

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

上記は同じです

cat <<EOF
This is coming from the stdin
EOF

または、次のようなコマンドからの出力をリダイレクトできます

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

またはあなたは次のように読むことができます

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

または単に

echo something | read param

そして、このようにバイナリ値を入力するにはどうすればよいですか?パイプを使用しない場合(パイプで次のように実行できることを知っていますecho -e "\x01\x02..." | ./script
cprcrack

私はそれを他の方法で書くのが好きです。
Pyrolistical 2014

@Pyrolisticalはい!たとえば、コマンドラインからperl onelinerを習得する場合に特に便利です。カーソルを使用して後方に大きく移動する必要なく、perlの引数を簡単に編集できます。:)
jm666 2014

@ jm666悲しいことは、bashエイリアスを使用する場合、昨日学んだことです。command_alias<<< "stdin string"の形式を使用するだけです。それ以外の場合は、コマンドが見つかりません
Pyrolistical

@ jm666私がもっと学ぶことができる場所はあり<<<ますか?今まで見たことがないことを恥ずかしく思っており、完全に不思議に思っています。私はそれのためにグーグルを試みました、しかし私の結果は無関係でした。
wpcarro

66

あなたは近かった

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

複数行の入力には、ヒアドキュメントが適しています:

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

コメントを編集

バイナリ入力を実現するには、

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

あなたが代わりcat/my/bash/script(または実際に最後のパイプをドロップ)した場合、これは出力します:

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

または、もう少しマニアックなものが欲しければ:

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?

4バイトバイナリフロートの最初の90度の正弦


そして、このようにバイナリ値を入力するにはどうすればよいですか?
cprcrack

私が使用したいxxd -r(またはod)HERE文書をフィルタリングする
sehe

例を挙げて説明してもらえますか?なんとかできませんでした。
cprcrack

1
編集された回答を参照してください。重要なのは、スクリプトに生のバイナリデータを含めず、代わりにxxdのようなプログラムでフィルタリングすることです
sehe

「/ my / bash / script <<< 'この文字列はstdinに送信されます。 「」?
白岩黄

2

readこのようにも使えます

echo "enter your name"
read name
echo $name

2

解決

(1)1つのプロセス(などecho '…')でstdout出力を作成し、(2)その出力を別のプロセスのstdin入力にリダイレクトするが、(3)bashパイプメカニズムを使用しない場合。3つの条件すべてに一致するソリューションは次のとおりです。

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

<標準入力のための通常の入力のリダイレクトです。これ<(…)はbashプロセスの置換です。おおまかに言って/dev/fd/…、置換コマンドの出力を含むファイルを作成し、そのファイル名をの代わりに渡します。<(…)これにより、たとえばのようになりscript < /dev/fd/123ます。詳細については、この回答を参照してください

他のソリューションとの比較

  • stdinに送信された1行のheredocはscript <<< 'string'、他のコマンドの出力ではなく、静的文字列の送信のみを許可します。

  • のようなプロセス置換だけでは、diff <(ls /bin) <(ls /usr/bin)標準入力に何も送信されません。代わりに、プロセスの出力は、たとえばと同等の、バックグラウンドで作成されたファイルのコンテンツとして渡されますdiff /dev/fd/10 /dev/fd/11。そのコマンドでdiffは、stdinから入力を取得しません。

ユースケース

パイプ機構とは異なり、私はそれが好きです < <(…)コマンドラインオプションからの入力の標準であるようにメカニズムではコマンドを最初に配置し、その後にすべての入力を配置できます。

ただし、コマンドラインの美学を超えて、パイプメカニズムを使用できない場合があります。例えば、特定のコマンドは、のように、別のコマンドの引数として提供されなければならないと、この例sshpass


興味深い代替案。これはたまたまPOSIX準拠<<<ですか?
すべてのワーカーは必須

0
cat | /my/bash/script

入力を履歴に保存したり、に表示したりせずに、プログラムに複数行を入力できるようにしpsます。入力が終了したら、Ctrl + Cを押して終了しcatます。


-1

エイリアスは、パイプされた標準入力を処理でき、処理できません...

ここでは3行の出力を作成します

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

次に、出力をsedコマンドのstdinにパイプして、すべてを1行に配置します

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

同じsedコマンドのエイリアスを定義すると

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

出力をエイリアスのstdinにパイプすることができ、それはまったく同じように動作します

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

エイリアスを関数として定義しようとすると問題が発生します

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

エイリアスを関数として定義すると、パイプが壊れます

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

まず、これは質問に答えません-おそらくあなたは間違った質問に答えましたか?次に、エイリアス内で関数を定義する理由は何ですか?あなたはただやるべきですfunction oline() { sed -e ":a;N;\$!ba ;s?\n? ?g"; }。第三に、sedのこれはawkを持つ多くのより理解しやすいでしょう:awk -F '\n' 'ORS=" " { print } END { printf "\n"}'
レオナルドDagnino
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.