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$
と実行すると、置換結果が文字列を追加したファイル名で保存できるんですね。
ちなみに、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コマンドは元々標準入出力の操作用なので、ファイルを直接書き換えるという操作は特殊ケースのようですね。
「やればできる 」と、「できる」は、違いますね。勉強になりました。