/dev/stdinとHeredocを使用してコマンドラインからファイルを渡す

/dev/stdinとHeredocを使用してコマンドラインからファイルを渡す

heredocsをコマンドラインユーティリティにファイルに渡す方法についての理論が疑問に思います。

最近、私はファイルをheredocに渡すことができることを発見しました。

たとえば、

awk '{ split($0, arr, " "); print arr[2] }' <<EOF
foo bar baz
EOF
bar

これは次の理由で私にとって有利です。

  • Heredocsは、複数行入力の読みやすさを向上させます。
  • コマンドラインからファイルの内容を渡すためにすべてのユーティリティフラグを覚えておく必要はありません。
  • 特定のファイルで一重引用符と二重引用符を使用できます。
  • シェルの拡張を制御できます。

たとえば、

ruby <<EOF
puts "'hello $HOME'"
EOF
'hello /Users/mbigras'

ruby <<'EOF'
puts "'hello $HOME'"
EOF
'hello $HOME'

何が起こったのかわかりません。シェルはheredocをheredocの値と内容が同じファイルと見なしているようです。私はこのスキルをcatと一緒に使ってみましたが、それでも何が起こっているのかわかりません。

cat <<EOL
hello world
EOL
hello world

私はcat印刷ファイルの内容を知っているので、おそらくこのheredocは一種の一時ファイルです。

「コマンドラインプログラムに区切り文字を渡す」とき、正確に何が起こっているのか混乱します。

以下は使用例です。可能なスクリプト。 PlayBookをheredocとしてユーティリティに渡しましたが、次の方法で失敗しましたecho $?

ansible-playbook -i localhost, -c local <<EOF &>/dev/null
---
- hosts: all
  gather_facts: false
  tasks:
    - name: Print something
      debug:
        msg: hello world
EOF
echo $?
5

しかし、同じheredocをユーティリティに渡しましたが、/dev/stdin成功する前に

ansible-playbook -i localhost, -c local /dev/stdin <<EOF &>/dev/null
---
- hosts: all
  gather_facts: false
  tasks:
    - name: Print something
      debug:
        msg: hello world
EOF
echo $?
0
  • 「区切り文字をファイルに渡す」と正確に何が起こりますか?
  • 最初のバージョンはansible-playbook失敗しましたが、2番目のバージョンが成功するのはなぜですか?
  • /dev/stdinheredocを通過することはどういう意味ですか?
  • なぜ他のユーティリティは以前heredocが好きrubyawk必要なのですか?/dev/stdin

ベストアンサー1

「区切られた文書をファイルに渡す」と正確に何が起こりますか?

あなたはそうではありません。ここでは標準入力を提供します。パイプのように。あなたの模範

awk '{ ... }' <<EOF
foo bar baz
EOF

まったく同じ

echo foo bar baz | awk '{ ... }'

awk、、、catおよびruby標準入力から読み取ったもの(コマンドラインに読み取ることができるファイル名が指定されていない場合)。これは実装の選択です。

anisble-playbookを含む最初のバージョンは失敗しますが、2番目のバージョンが成功するのはなぜですか?

ansible-playbookデフォルトでは標準入力からは読み込まれませんが、ファイルパスが必要です。デザインの選択です。

/dev/stdin/dev/fd/0現在のプロセスについて話す方法であるシンボリックリンクである可能性が高いです。ファイル記述子#0(標準入力)。これはカーネル(またはシステムライブラリ)によって公開されます。このansible-playbookコマンドは/dev/stdin通常のファイルシステムファイルのように開き、最終的に独自の標準入力を読み込みます。それ以外の場合は無視されます。

おそらくFD 1と2への/dev/stdoutリンクがあります/dev/stderr。これは、出力をどこに入れるかを知りたい場合にも使用できます。

区切り文字の前に/ dev / stdinを渡すのはなぜですか?

これはコマンドのパラメータですansible-playbook

Rubyやawkなどの他のユーティリティでheredocの前に/ dev / stdinを要求しないのはなぜですか?

デフォルトではパイプラインで使用するように設計されているため、標準入力をデザイン選択として読み込みます。同じ理由で標準出力に書き込みます。

おすすめ記事