私はここでこの質問をするハンマーポケットと同じくらい愚かな感じですが、長い一日が過ぎ、ここで何が間違っているのかわかりません。
ファイルがありますtextfile.txt
。その内容は(この代表的な例ですが操作された例では)次のとおりです。
文書内容
SOME=1
TRIED="THEIR BEST AT"
INSERTING='A VALUE'
BE=4
それでは、2つの変数があるとし、$KEY
ファイル$VAL
から更新したいキーと値を表すものがあるとしましょう。ナレーター:どちらも引用符["]またはアポストロフィ[']を含めないことを保証できます。):
新しい価値
KEY="TRIED"
VAL="THEIR HAND AT"
わかりました。今、私は沼地標準正規表現置換のように見えることをトリガしています(交換された値が何でも含めようとしていることに注意してください)。任意に選択できる現在、周囲に区切り文字があります):
sed -E "s/$KEY=([\"']?).*([\"']?)/$KEY=\1$VAL\2/g" textfile.txt > textfile.txt
予想される結果
SOME=1
TRIED="THEIR HAND AT"
INSERTING='A VALUE'
BE=4
実際の結果
(空のファイル)
わかりました、わかりました。私のターゲットが私が読んでいるファイルではなく新しいファイルであればどうなりますか?
sed -E "s/$KEY=([\"']?).*([\"']?)/$KEY=\1$VAL\2/g" textfile.txt > textfile2.txt
新しい結果
SOME=1
TRIED="THEIR HAND AT
INSERTING='A VALUE'
BE=4
首都!
AT
...今、値の周りに2番目の区切り文字(末尾の二重引用符)がありません。再利用可能で動作します\1
が、壊れやすい感じがし、ボールがどこに落ちるのかわかりません。
だから...質問:
- 最初の試みでファイルが完全に消去されるのはなぜですか?
- 2番目の区切り文字で後者の区切り文字が省略されているのはなぜですか?
私はこのアプローチがまったく好きではなく、別の道を行くかもしれませんが、誰かがこれらの2つのことを説明してくれたらとても感謝しています。昨日私に尋ねたら、RegExを知っていると誓った。分シェルで使ったからです。
私はVentura 13.0の2021 MacBook M Chip ProでGNU bashバージョン5.2.12を実行しています(助けになれば)。
答え1
-i
スイッチがなく、スイッチsponge
がある場合moreutils
、あなたはできます:
sed 's///g' file | sponge file
このツールは、この目的のために特別に設計されています。
答え2
まあ、これは少し掘削が必要でした。 don_crissti(出力をクリアする妥当な理由を指摘してくださった)とGilles Quenot(理解しようと非常に難しいウサギに送ってくださったsponge
)に感謝します。
ただし、最終的な最終結果は次のとおりです。
>
これは/リダイレクトを使用する>>
ときに予想される動作であるため、ファイルの内容は消去されます。残りのコマンドの前にリダイレクトが実行されるため、読んでいるファイルを消去してクリーンアップして(何もリダイレクトして)、コマンドの結果をそのファイルに書き込むことはできません。これはファイルです(読み込んだファイルは空でリダイレクトが発生したためです)。この場合、回避策は一時ファイルを作成してすぐにソースファイルを上書きすることです。
sed -E "s/$KEY=([\"']?).*([\"']?)/$KEY=\1$VAL\2/g" textfile.txt > textfile.tmp && mv textfile.tmp textfile.txt
これは、GNUのあまり強力なバイナリバージョンを使用するMacOSの不幸な結果であり、
sed
GNUバージョンを取得してもbrew install gsed
基本バージョンを安全に置き換えることができないため、移植性と将来の保証が不可能になります。...しかし、まだ「消える文字列区切りケース」という重い負担を抱いています。しかし、調査中に、私はDarwinバージョンのツールで正規表現の拡張変数を使用することに関する興味深い事実を偶然発見しました。拡張で変数名をラップして 'を避けなければ
sed
なりませんでした。$
したがって、
sed -E "s/$KEY=([\"']?)
[...]などの代わりに必要な構文はsed -E "s/\$(KEY)=([\"']?)
[...]などです。$
さらなる調査結果によれば、以下のように各変数を簡単にエスケープ処理すればsed -E "s/\$KEY=([\"']?)
[…]などが可能になりました。...私はまた望ましい結果を得ることができますが、私よりも率直なLinuxベテランは、
$(VARIABLE)
この場合構文がより安全であると提案します(理由はわかりませんが)。
この後続の記事が同じ問題を抱えている他の人に役立つことを願っています。正しい方向を教えてくれたdon_crisstiとGilles Quenotに感謝します! <3