コマンドラインから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
はファイルの内容であり、検索と置換が実行されました。
なんでこんなことが起こっているの?
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などの一部のプラットフォームでコマンドが失敗します。
代替的で便利なパターンは次のとおりです。
sed -e 'script script' index.html > index.html.tmp && mv index.html.tmp index.html
-i
オプションを使用しなくても、これはほぼ同じ効果があり、さらに、sedスクリプトが何らかの理由で失敗した場合に入力ファイルが壊れていないことを意味します。さらに、編集が成功した場合、バックアップファイルは残っていません。この種の慣用句はMakefileで役に立ちます。
かなりの数のsedsに-i
オプションがありますが、全部ではありません。 posix sedはそうではありません。あなたが移植性を狙っているのであれば、それゆえ、それは避けるのが最善です。
sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' index.html
これにより、ファイルindex.htmlのグローバルなインプレース置換が行われます。文字列を引用符で囲むと、クエリ内の空白や置換の問題を防ぐことができます。
sedの-iオプションを使用してください。
sed -i bak -e s/STRING_TO_REPLACE/REPLACE_WITH/g index.html
複数のファイルを変更する(そしてそれぞれのバックアップを* .bakとして保存する)には:
Perl -p -i -e "s/\|/x/g" *
ディレクトリ内のすべてのファイルを取り、|
をx
に置き換えます。これは「Perlパイ」と呼ばれます(パイと同じように簡単です)。
インプレース編集にはオプション-i
を使用してみてください。
警告:これは危険な方法です! 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番目のバージョンも機能します。
sed -i.bak "s#https.*\.com#$pub_url#g" MyHTMLFile.html
追加するリンクがある場合は、これを試してください。上記のようにURLを検索し(ここではhttpsで始まり、ここではcomで終わります)、それをURLストリングに置き換えます。ここでは変数$pub_url
を使いました。ここでのs
は検索を意味し、g
はグローバル置換を意味します。
できます !
コマンドの問題
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
そして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"コマンドを呼び出します。今は空のファイルです。
ExモードでVimを使うことができます。
ex -sc '%s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g|x' index.html
%
すべての行を選択
x
保存して閉じる
行範囲を定義して答えを見つけることができるオプションを探していました。たとえば、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
上記の正しい答えを念頭に置いて、そのようなスクリプトを「ドライラン」して、ファイルを破損しないようにして最初からやり直す必要があるようにすることをお勧めします。
たとえば、次のようにスクリプトでファイルに出力するのではなく、出力をコマンドラインに書き出すようにします。
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
これにより、ファイルを切り捨てることなくコマンドの出力を確認して確認できます。