web-dev-qa-db-ja.com

ファイル内の検索と置換、およびファイルの上書きは機能しません。ファイルを空にします。

コマンドラインからHTMLファイルの検索と置換を実行したいです。

私のコマンドはこのようになります:

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html > index.html

これを実行して後でファイルを見ると、空です。それは私のファイルの内容を削除しました。

ファイルを再度復元した後にこれを実行すると、

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

stdoutはファイルの内容であり、検索と置換が実行されました。

なんでこんなことが起こっているの?

570
BBales

Shell がコマンドラインで> index.htmlを見ると、 writing のためにファイルindex.htmlを開き、それまでの内容をすべて消去します。

これを修正するには、sed-iオプションを渡して変更をインラインにし、元のファイルのバックアップを作成してから変更をインプレースする必要があります。

sed -i.bak s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

.bakがないと、Mac OSXなどの一部のプラットフォームでコマンドが失敗します。

874
codaddict

代替的で便利なパターンは次のとおりです。

sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html

-iオプションを使用しなくても、これはほぼ同じ効果があり、さらに、sedスクリプトが何らかの理由で失敗した場合に入力ファイルが壊れていないことを意味します。さらに、編集が成功した場合、バックアップファイルは残っていません。この種の慣用句はMakefileで役に立ちます。

かなりの数のsedsに-iオプションがありますが、全部ではありません。 posix sedはそうではありません。あなたが移植性を狙っているのであれば、それゆえ、それは避けるのが最善です。

201
Norman Gray
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html

これにより、ファイルindex.htmlのグローバルなインプレース置換が行われます。文字列を引用符で囲むと、クエリ内の空白や置換の問題を防ぐことができます。

86
Rich Apodaca

sedの-iオプションを使用してください。

sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
56
Kevin

複数のファイルを変更する(そしてそれぞれのバックアップを* .bakとして保存する)には:

Perl -p -i -e "s/\|/x/g" *  

ディレクトリ内のすべてのファイルを取り、|xに置き換えます。これは「Perlパイ」と呼ばれます(パイと同じように簡単です)。

18
Stenemo

インプレース編集にはオプション-iを使用してみてください。

14
uloBasEI

警告:これは危険な方法です! LinuxのI/Oバッファを悪用し、バッファリングの特定のオプションを使用して、小さなファイルを処理します。興味深い好奇心です。 ただし、実際の状況では使用しないでください!

sed-iオプションに加えて、teeユーティリティを使用できます。

manから:

tee-標準入力から読み取り、標準出力およびファイルに書き込みます

したがって、解決策は次のようになります。

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee | tee index.html

-ここでは、teeが繰り返され、パイプラインがバッファリングされていることを確認します。その後、パイプライン内のすべてのコマンドは、入力を取得するまでブロックされます。パイプライン内の各コマンドは、アップストリームコマンドがコマンドの入力に1バイトのバッファー(サイズは somewhere で定義されています)を書き込むと開始します。したがって、書き込み用にファイルを開いて空にする最後のコマンドtee index.htmlは、アップストリームパイプラインが終了し、出力がパイプライン内のバッファーにある後に実行されます。

ほとんどの場合、以下は機能しません。

sed s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html | tee index.html

-ブロックなしでパイプラインの両方のコマンドを同時に実行します。 (ブロックせずに、パイプラインは、バッファごとにではなく、行ごとにバイトを渡す必要があります。cat | sed s/bar/GGG/を実行する場合と同じです。バッファされます。)tee index.htmlは書き込み用にファイルを開き、空になります。ただし、バッファリングを常にオンにすると、2番目のバージョンも機能します。

6
xealits
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html

追加するリンクがある場合は、これを試してください。上記のようにURLを検索し(ここではhttpsで始まり、ここではcomで終わります)、それをURLストリングに置き換えます。ここでは変数$pub_urlを使いました。ここでのsは検索を意味し、gはグローバル置換を意味します。

できます !

6
Kaey

コマンドの問題

sed 'code' file > file

sedが実際に処理を開始する前に、fileがシェルによって切り捨てられるということです。その結果、あなたは空のファイルを取得します。

他の回答が示唆しているように、これを行う賢い方法は-iを使ってその場で編集することです。しかし、これは必ずしもあなたが望むものではありません。 -iは一時ファイルを作成し、それが元のファイルを置き換えるために使用されます。元のファイルがリンクだった場合、これは問題になります(リンクは通常のファイルに置き換えられます)。リンクを保存する必要がある場合は、次のように一時変数を使用してsedの出力をファイルに書き戻す前に保存できます。

tmp=$(sed 'code' file); echo -n "$tmp" > file

もっと良いのは、printfはいくつかのシェルでは\\\として処理する可能性が高いので(例:ダッシュ)、echoの代わりにechoを使用します。

tmp=$(sed 'code' file); printf "%s" "$tmp" > file
4

そしてed答え:

printf "%s\n" '1,$s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' w q | ed index.html

codaddictが と答えたことを繰り返すために、シェルはリダイレクション first を処理して "input.html"ファイルを消去し、then _は "sed"コマンドを呼び出します。今は空のファイルです。

3
glenn jackman

ExモードでVimを使うことができます。

ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
  1. %すべての行を選択

  2. x保存して閉じる

2
Steven Penny

行範囲を定義して答えを見つけることができるオプションを探していました。たとえば、Host 1をHost 2に36-57行目から変更します。

sed '36,57 s/Host1/Host2/g' myfile.txt > myfile1.txt

大文字小文字の区別を無視するためにgiオプションを使うこともできます。

sed '30,40 s/version/story/gi' myfile.txt > myfile1.txt
0
user8117884

上記の正しい答えを念頭に置いて、そのようなスクリプトを「ドライラン」して、ファイルを破損しないようにして最初からやり直す必要があるようにすることをお勧めします。

たとえば、次のようにスクリプトでファイルに出力するのではなく、出力をコマンドラインに書き出すようにします。

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html

OR

less index.html | sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g 

これにより、ファイルを切り捨てることなくコマンドの出力を確認して確認できます。

0
Nestor Milyaev