シェル: GNU BASH
私はしばらく次のコマンドを使用してきました。
echo "$(fmt -w 50 < foo.txt)" > foo.txt
問題ありません。しかし試してみるとき:
fmt -w 50 < foo.txt > foo.txt
foo.txtファイルは空のファイルになります。これは、シェルから解析するリダイレクト演算子がサブシェルの優先順位に関連しているためだと思います。
GNU BASH マニュアルを検索しても結果が出ませんでした。マニュアルに何か抜けたのか誰か教えてもらえますか?私はこの動作の原因を理解して、それをさらに活用し、問題を引き起こす可能性があるすべての状況を理解できることを願っています。
答え1
Bashのマニュアルでは、3.7.1 簡単なコマンド拡張:
単純なコマンドを実行すると、シェルは左から右に次の拡張、割り当て、およびリダイレクトを実行します。
コマンド置換は、(2) で発生する拡張の 1 つであり、(3) で拡張後にリダイレクトが発生します。これは、サブシェルとは無関係であり、純粋にシェルが操作を実行する順序によるものです。(fmt -w 50 < foo.txt) > foo.txt
空のファイルも作成されます。
答え2
人々が利用できるsponge
公益事業:
fmt -w 50 < foo.txt | sponge foo.txt
原文に関する注意事項:
echo "$(fmt -w 50 < foo.txt)" > foo.txt
最初に実行されるのは、
fmt
出力がひも、つまり二重引用符で囲まれた内容です。fmt
完了するまで他のことは起こりません。echo
文字列を次に印刷します。標準出力。その間、
echo
出力は>
次にリダイレクトされます。foo.txt。
ステップ2と3はほぼ同時に発生します。
元のコードには実際に問題があります。コマンドラインに長さ制限。入力したらfoo.txt非常に大きく、特に長さが大きい場合、getconf ARG_MAX
コマンドecho
は失敗または不完全な結果を提供します。