Javaで正規表現を扱うのは難しい
今日他の人が書いたJavaのプログラムを読んでいたら、正規表現でパターンにマッチした領域をListの要素で置換するという処理がありました。具体的に言うと、
["要素1", "要素2"]
のようなListが与えられていた場合、"test #{0} #{1} test"のようなテンプレート文字列を"test 要素1 要素2 test"のようにフォーマットする処理です。もともとのコードは正規表現のAPIを使って#{}の部分をマッチさせてはいたのですが、結局Stringのsplit()メソッドやreplace()メソッドをループ内で何度も繰り返し適用して大量の文字列オブジェクトを生成していて、とてもイケテない実装になっていました。
きっと初心者の方が書いたに違いない、このようなのはもっとずっと簡単に実装できるはずだと思って、気軽にリファクタリングを始めてみたのですが、Javaの正規表現のAPIを使った文字列置換のイディオムが完全に頭に入っていなかったこともあり、結構はまって時間がかかってしまいました。
一応、正解としては、以下のようなコードになると思います。
private static final Pattern patten = Pattern.compile("\\#\\{(.+?)\\}"); public String expandData(String template, List<String> data) { Matcher matcher = patten.matcher(template); StringBuffer sb = new StringBuffer(); while (matcher.find()) { String strIndex = matcher.group(1); int index = Integer.parseInt(strIndex); matcher.appendReplacement(sb, data.get(index)); } matcher.appendTail(sb); return sb.toString(); }
最近はこのような処理はEL式の処理用ライブラリーなどに任せてしまうことが多く、Javaで正規表現を直接扱うようなコードをあまり書いていないため、自分のスキル不足だなとは思いましたが、やはりJavaだと難しいですね。RubyやGroovyのgsub()メソッドなどの感覚と比べると相当面倒です。ちなみに、以下を参考にさせていただきました。
Javaの道:文字列(7.正規表現)