シェルパイプラインはあまりにも強力で、時には残念です。
はい
同じたとえば、パイプ
echo abc > file.txt
cat file.txt | sed 's/a/1/' > file.txt
空のものをくださいfile.txt
。シェルが>
最初に呼び出される可能性があることに気づき、変更しました。
echo abc > file.txt
{cat file.txt | sed 's/a/1/'} > file.txt
別の空のファイルが私をまた驚かせたfile.txt
。結局、効果があった醜いアプローチは次のとおりです。
echo abc > file.txt
echo $(cat file.txt | sed 's/a/1') > file.txt
これにより、シェルは最初にサブシェルを実行してからリダイレクトされます。
質問
、、...などをsed
削除するより良い方法を知っていますが、ここで気になるのはシェルの構文を徹底的に学ぶことです。echo
cat
grep
この質問は、上記の特定の問題を解決する方法に関するものではありません。
Q1(編集者:トピック以外)文法を学ぶときに使用できる良い資料はありますか?
シェルごとに構文が異なる場合があるので心配です。
第2四半期シェルを冗長にしてコマンドを実行するたびに、シェルが何をしているのかを正確に確認できますか?
Q3(編集:トピックから抜け出す)ベストプラクティスのための他の提案はありますか?ありがとうございます!
答え1
考える3.1.1 シェル動作、特に操作が実行される順序は次のとおりです。
- リダイレクト処理済み今後実際にコマンドが実行されますが、
- 拡張はリダイレクト前に処理されます。
これは、cat file > file
出力リダイレクト(ファイル切り捨て)がcat
ビルド前に発生し、cat
作業する空のファイルがあることを意味します。
しかしecho "$(cat file)" > file
予想したようにコマンドの置き換えはシェル拡張、これはリダイレクト前に発生します。
典型的なアドバイスは
cat file > tmpfile && mv tmpfile file
あなたはそれを使用することができますmktemp
ここで。
または、moreutils
パッケージをインストールして使用してください。sponge
cat file | sponge file
使用している特定のコマンドを解決するには、次の変更を行います。
cat file.txt | sed 's/a/1/' > file.txt
(GNU sedと仮定)
sed -i 's/a/1/' file.txt
答え2
してはいけないことの1つをうまく見つけました。 :-) 作業中のファイルにリダイレクトしないでください。
A1:シェル構文を学ぶための良いリソースは次のとおりです。Bash スクリプトのための絶対ガイド、国際海事機関
A2:Bashスクリプトの場合は、より詳細な出力を使用できますが、set +x
「プロンプトで実行」レベルで同じ結果を取得する方法がわかりません。
A3:[solved]
クエリに追加してください。既に知っている問題ではなく、問題に対する解決策を見つけてください。
答え3
問題を解決する1つの方法は、順次リダイレクト、拡張、サブシェルなどが何が起こるのかを正確に理解して、これらのエラーが発生する前にキャッチできるようにすることです。
私はこれをお勧めしません。時にはまだ混乱してデータが失われる可能性があります。
楽しむいいえこれらすべてを正しく維持し、より愚かなコードを書く能力を信じてください。 私たちは皆時々愚かです。
だから
cp file.txt file.txt.old
cat file.txt.old | sed 's/a/1/' > file.txt
これは、ライン1がライン2よりも先に発生することを除いて、イベントの順序に依存しないので、より単純である。
追加の利点として、その他まったく実行しないでください。このスクリプトを実行するとエラーが発生します。
このアプローチのコストは、.old
ファイルがどこにでもあるということです。必要な日にお支払いいただき、喜ぶプレミアムです。皿は非常に安いです。