-
複数行にわたる範囲をgrepしたいときはpcre2grepを使おう
- 2020年8月25日
- Git
- grep
結論
pcre2grep で -M オプションを使うと、複数行にわたる範囲を対象にgrepできます。
いきさつ
とあるプロジェクトで広範囲なコードの書き換えが並行して行われていたのですが、案の定派手にコンフリクトします。
その際、レビュワーに「コンフリクトの内容の一覧を出した上で解消してほしい」と依頼されました。
プログラマーたるもの、ちまちまコピペなんてしてられないですよね。
方針
ぼんやりと以下のように考えます。
- ディレクトリ配下を全なめして、コンフリクト箇所の印である
<<<<<<<<と>>>>>>>>に囲まれた範囲を抜き出してやればいいなー- この時点でほぼgrepを使うことになりそうです
- ディレクトリ配下の再帰的な探索はgrepの
-rオプションでできます
- レビューに使うならファイル名と行数もつけないとわかんなくなるなー
- grepは
-rオプションを使えば自動的にファイル名がつきます - 行数は
-nオプションを使えばつきます
- grepは
- 1つのテキストファイルに収めないと読みづらいなー
-rオプションを使うので自然とそうなります
grepしてみた
※以下は動きません
grep -nr '<<<<<<<[\s\S]*?>>>>>>>' .
2つ勘違いしています。
- 通常のgrepはPerl互換正規表現 (上記の
\s\S) を使えない- 一応 GNU grep には
-Pオプションがありますが、macにもともと入ってるやつはBSD版なので使えません……
- 一応 GNU grep には
- 通常のgrepは複数行にわたる範囲を検索できない
- もともと「行を検索する」コマンドなので……
まとめて解消していく
pcre2grep を使います。
pcreとは Perl-compatible Regular Expressions 、すなわちPerl互換正規表現のことです。
pcre2grepには -M, --multiline というオプションがあり、その名の通り複数行の範囲を検索してくれます。
というわけで、以下のようなコマンドになります。
pcre2grep -Mnr '<<<<<<<[\s\S]*?>>>>>>>' .
以下のような出力が得られます。素敵ですね。
./hoge.txt
27:<<<<<<< HEAD
ほげほげ
=======
ふがふが
>>>>>>> topic
./piyo/piyo.txt
5:<<<<<<< HEAD
ぴよぴよ
=======
ぽよぽよ
>>>>>>> topic
20:<<<<<<< HEAD
ぴよぴよぴよ
=======
ぽよぽよぽよ
>>>>>>> topic
あとはパイプして pbcopy に突っ込むなり、テキストファイルにリダイレクトするなりすればOKです。
(おまけ)不要なディレクトリを除外して速度を上げる
プロジェクトルートで先のコマンドを実行すると、結構時間がかかります。
それもそのはず、一般的なプロジェクトならあるであろう依存性のディレクトリやビルド結果のディレクトリ、果ては .git/ まで舐めているからです。
--exclude-dir というオプションがあるので、それを使って検索対象から除外するフォルダを指定します。
{} で囲んで , で区切ると複数指定できます。
今回のプロジェクトはReact (すなわちNode.js) を使ったプロジェクトだったので、最終的に以下のようになりました。
pcre2grep -Mnr --exclude-dir={.git,build,node_modules} '<<<<<<<[\s\S]*?>>>>>>>' .
今後も面倒なことはなるべく機械にやらせていきたいですね。
この記事を書いた人 : 池上龍一
AWS bluebird css CSV docker docker compose electron ES6 es2015 Git Heroku ITコンサルティング JavaScript justinmind less MongoDB Node.js php PostgreSQL Private Space Promise React react-router reactjs Salesforce scss Selenium Builder selenium IDE Selenium WebDriver stylus TypeScript VirtualBox VisualStudioCode vue vuejs webpack システム開発プロジェクト セキュリティ ワイヤーフレーム 上流工程 卒FIT 帳票 要件定義 設計 電力小売業界