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/stdin
heredocを通過することはどういう意味ですか?- なぜ他のユーティリティは以前heredocが好き
ruby
かawk
必要なのですか?/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を要求しないのはなぜですか?
デフォルトではパイプラインで使用するように設計されているため、標準入力をデザイン選択として読み込みます。同じ理由で標準出力に書き込みます。