nisshi9の備忘録ブログ

気まぐれなタイミングで、興味のわいた事について書いていくブログです。

MacOSXで複数ファイル内の文字列置換をしようとしたらハマった話

久しぶりのブログ記事になります。

 

ひょんなことから、html内の文字列を部分置換する必要が発生しました。

おまけに、htmlファイルは100以上あり、全部に置換が必要な状況。

とはいえ、macbook proを使っているので、sed/awkを使うことを思いつく。

 

 


sedを使って複数ファイルの文字列を一気に置換する - プログラミングのメモ

 

コマンドの意味の解説は他のサイトに譲りますが、簡単に説明すると、

「 xargs 」で前のコマンドの実行結果を利用することができます。

sed -i 」で直接ファイルを編集できます。

ところがやってみると、エラーが出る。

sh-3.2$ find ./ -name test.html|xargs sed -i "s/javascript/JAVASCRIPT/g"
sed: 1: ".//hoge/test.html": invalid command code . 

 

調べてみると、BSD系は「 - i 」の扱いが違うらしく、「 -i '' 」と書いてやると良いらしい。


sed: 1: file: extra characters at the end of l command | Karlosp.net

 

ということなので、やってみる。

sh-3.2$ find ./ -name test.html|xargs sed -i '' "s/javascript/JAVASCRIPT/g"
sh-3.2$

 

今度は何もエラーを出さずに終了。めでたし、めでたし。

ちなみに、ちゃんと調べずに、試行錯誤していて気づいたのですが、

「 -i 」の後ろに文字列を挿入して、

sh-3.2$ find ./ -name test.html|xargs sed -i STRING "s/javascript/JAVASCRIPT/g"
sh-3.2$

と実行すると、置換結果が文字列を追加したファイル名で保存できるんですね。

sh-3.2$ ls hoge/test*
hoge/test.html        hoge/test.htmlSTRING

 

ちなみに、manコマンドでsedについて調べると、「 -i 」について調べると、以下のように書いてありました。

     -i extension
             Edit files in-place, saving backups with the specified extension.  If a zero-length extension is given, no backup will be saved.  It is not rec-
             ommended to give a zero-length extension when in-place editing files, as you risk corruption or partial content in situations where disk space
             is exhausted, etc.

in-placeの意味のようです。また、直接書き換えという解釈は間違っていないようなのですが、このオプションを使うと、指定した拡張子でバックアップでき、長さが0の引数を与えた場合はバックアップなしで保存するようです(直接書き換え)。長さ0の引数を与えると、元のファイルが上書きされるので、おすすめしないよ。とのことです。

そもそも、sedコマンドは元々標準入出力の操作用なので、ファイルを直接書き換えるという操作は特殊ケースのようですね。

 

「やればできる 」と、「できる」は、違いますね。勉強になりました。