Bashが次の行を正確に処理する方法を理解しようとしています。
$(< "$FILE")
Bashのマニュアルページによると、これは次のようになります。
$(cat "$FILE")
2行目から推論の流れに従うことができます。 Bashは入力コマンドの置換時に変数拡張を実行して$FILE
値をに渡し、catはOrderの内容を出力します。$FILE
cat
$FILE
ただし、上記の最初の行の場合は、次のように解釈します。 Bashはで変数置換を実行し、Bashは標準入力から読み取るために$FILE
開きます。$FILE
何らかの方法で標準入力を標準出力にコピーします。、コマンド置換が完了し、Bashは生成された標準出力を実行しようとします。
$FILE
コンテンツがstdinからstdoutにどのように移動するかを説明できますか?
ベストアンサー1
$(<file)
(ksh93でも、`<file`
およびで使用されます)は、およびからコピーされた${<file;}
Kornシェルの特殊演算子です。コマンドの置換と非常に似ているようですが、そうではありません。zsh
bash
POSIXシェルでは、単純なコマンドは次のとおりです。
< file var1=value1 > file2 cmd 2> file3 args 3> file4
すべての部分はオプションであり、リダイレクトのみ、コマンドのみ、割り当てのみ、または組み合わせることができます。
リダイレクトがありますが、コマンドがなければリダイレクトは行われますが(したがってaが> file
開かれ、切り捨てられますfile
)、何も起こりません。だから
< file
読み取り用に開かれますfile
が、コマンドがないため、何も起こりません。その後、file
終了しました。$(< file)
簡単なものならコマンドの置き換えすると、空の状態に展開されます。
内部にPOSIX仕様、inにリダイレクトのみが含まれている$(script)
場合script
指定されていない結果が発生しました。これは Korn シェルの特別な動作を可能にするためのものです。
ksh(ここでテスト済みksh93u+
)でスクリプトに1つしか含まれていない場合簡単なコマンド(コメントは前後に許可されますが)リダイレクト(コマンドなし、割り当てなし)のみが含まれ、最初のリダイレクトがstdin(fd 0)の場合(<
、<<
または<<<
)リダイレクトのみを入力すると、次のようになります。
$(< file)
$(0< file)
$(<&3)
($(0>&3)
実際にこれは実際には同じ演算子なので)$(< file > foo 2> $(whatever))
しかし:
$(> foo < file)
- ...でもない
$(0<> file)
- ...でもない
$(< file; sleep 1)
- ...でもない
$(< file; < file2)
それから
- 最初のリダイレクトを除くすべてのリダイレクトは無視されます(解析され削除されます)。
- file/heredoc/herestring(または同様のものを使用する場合は、ファイル記述子から読み取ることができるすべての項目)の内容から
<&3
末尾の改行文字を引いたものに展開されます。
$(cat < file)
それを除いては使用感に似ています。
- 読み取りはシェルではなく内部で行われます。
cat
- 配管や追加のプロセスは必要ありません。
- 上記と同じ理由で、内部コードはサブシェルで実行されないため、すべての変更(たとえば、
$(<${file=foo.txt})
または$(<file$((++n)))
)はその後も保持されます。 - 読み取りエラー(ファイルを開いたりファイルディスクリプタをコピーしたときに発生するエラーではありません)は自動的に無視されます。
では、ファイル入力リダイレクト(または、no、...)zsh
が1つしかない場合にのみ特殊動作がトリガされることを除いて同じです。<file
0< file
<&3
<<<here
< a < b
しかし、他のシェルをシミュレートすることに加えて、つまり、< file
コマンドなしで入力リダイレクトが1つしかない場合は、コマンド置換の外部でzsh
実行$READNULLCMD
(デフォルトではポケットベル)で、リダイレクトが多いか< file
(<&3
、、、、.. )(デフォルト)であるため、対応<<<text
する特殊演算子として認識されなくても、呼び出して実行したように動作します。<a <b
>file
<a >b
$NULLCMD
cat
$(<&3)
ksh
cat
ただし、の内容ksh
は次に展開されますが、$(< a < b)
inの内容は次の内容に展開されます。a
zsh
a
そしてb
(またはそのオプションが無効になっている間b
)コピーされ、空の状態に展開されます。multios
$(< a > b)
a
b
bash
同様の演算子がありますが、いくつかの違いがあります。
コメントは以前は許可されていますが、その後は許可されません。
echo "$( # getting the content of file < file)"
動作しますが:
echo "$(< file # getting the content of file )"
何も膨らませなかった。
のように、
zsh
stdinのファイルリダイレクトは1つだけですが、aへのフォールバックはないため、リダイレクトは行われますが、$READNULLCMD
拡張子は空です。$(<&3)
$(< a < b)
何らかの理由で
bash
呼び出していない場合でも、cat
プロセスを分岐してファイルの内容をパイプするため、他のシェルよりも最適化がはるかに少なくなります。実際に組み込まれたのと同じです$(cat < file)
。cat
cat
上記の理由により、変更は失われます(
$(<${file=foo.txt})
たとえば、上記の場合は割り当てが$file
失われます)。
((適用))は、コンテンツを読むためのより効率的な方法ですbash
。IFS= read -rd '' var < file
zsh
テキスト変数にファイルを置きます。また、末尾の改行文字を保存できるという利点もあります。また、($mapfile[file]
モジュールでは、通常のファイルのみ)バイナリファイルでも機能します。zsh
zsh/mapfile
pdksh ベースのバリアントにはksh
ksh93 に比べていくつかの変更があります。興味深いことにmksh
(pdksh派生シェルの1つ)から
var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)
ここにある文書のように、一時ファイルやパイプを使わずに、ここの文書の内容(末尾改行なし)が拡張され、有効な複数行参照構文になるため最適化されました。
ksh
、zsh
およびのすべてのバージョンへの移植性のために、コメントを避け、変数の変更が維持されても維持されない可能性があることを覚えておくのがbash
最善です。$(<file)