Linux:複数ファイル内の文字列を一括置換
'hoge'が含まれているファイルを検索
$ grep -l 'hoge' *
-l, --files-with-matches PATTERN に一致する FILE の名前のみ表示する
複数ファイルの文字列を一括置換
ファイル内の'hoge'を'hage'に置換する例。
$find ./ -type f | xargs sed -i 's/hoge/hage/g'
or
$ sed -i 's/hoge/hage/g' *
オプション
- i 入力ファイルの上書き
- g 1行中に複数マッチしたら全部置換
改行を含む複数行にマッチさせる場合
sedで複数行を扱うにはループという非常にややこしい書式になるので、Perlを使う
$ find . -name '*.md' | xargs perl -0pi -e 's/検索文字\n検索文字/置換文字\n置換文字\n置換文字/m'
-pでprint
コマンドライン中の文字列をスクリプトとして解釈させるには、-eを使う。
-iを指定すると、ファイルの出力は入力元となったファイル自身になる。
-pはデフォルトでは1行ずつ-eの引数を評価する。つまりセパレータが\n。
-0でセパレータがヌル文字(\0)になる。つまり、ファイル全体を一度に読み込むことになる(よって、巨大なファイルに実行するのはおすすめしない)。
また、正規表現のオプション修飾子にmを指定し複数行モードにする(s/hoge/fuga/m←このm)
区切り文字はなんでもいい
$find ./ -type f | xargs sed -i 's%hoge%hage%g'
カレントディレクトリを起点にするときは、以下同じ意味
$ find ./
$ find .
$ find
sed のスクリプトで使う メタ文字
- ^ 先頭
- $ 後尾
- . 任意の 1 文字
- * 直前の文字の 0 回以上の繰り返し
- \+ 直前の文字の 1 回以上の繰り返し
- \? 直前の文字が 0 回または 1 回のみ出現
- [] 文字クラス、[abc0-9] ならば数字と a, b, c のどれか 1 文字
- \| OR、[ab|ap] ならば ab または ap
- \{3\} 直前の文字が 3 回だけ出現
- \{3,5\} 直前の文字が 3〜5 回出現
- \b 単語区切り
\?とか忘れて、[0-9]? とやってしまうと、「数字と?という文字」にマッチになってしまうので、あれれ?となる。
スクリプトとは、sedのオプションで -e を指定したときの条件式。これがデフォルト。
正規表現を使うこともできて、オプションで -r を指定する。その場合は、メタ文字じゃなくて、普通の正規表現が使える。
つまり、[0-9]? は数字一文字があってもなくてもよい、になる。
以下全部一緒の動作
sed 's%hoge[0-9]\?%hage%g' input.txt
sed -e 's%hoge[0-9]\?%hage%g' input.txt
sed -r 's%hoge[0-9]?%hage%g' input.txt