【Java】正規表現 ~ 文字列の抽出 ~

■ はじめに

今回は、JavaのMatcher.group()を使って
文字列の抽出を行う。

【1】基礎知識

* パターンの中で、マッチした部分を取り出したい部分を括弧()で囲う

1)構文

// 1, 2, ...
String result1 = matcher.group(1);
String result2 = matcher.group(2);
...

参考文献
http://www.javadrive.jp/regex/ref/index2.html

【1】サンプル

例1:正規表現で文字列抽出

* 「【任意文字】Version【空白】:【空白】XXXXX【空白】」のフォーマットで
    "XXXXX"部分を抽出する

Main.java

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

  public static void main(String[] args) {
    Pattern pattern = Pattern.compile("^.*Version[ \\t]*:[ \\t]*(.*)[ \\t]*$");
    Matcher matcher = pattern.matcher(" Version : 1.0.1");
    if (matcher.matches()) {
      System.out.println("Result : " + matcher.group(1));
    }
  }
}

出力結果

Result : 1.0.1

例2:コード内の要素分割

* コード「【文字(A-Z)】【数字(2桁)】【文字(A-Z)】【数字(連番)】」
 のフォーマットで各要素を分割し、抽出する。

CodeSplitter.java

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CodeSplitter {

  public static void main(String[] args) {
    // Ex1
    System.out.println("**********************");
    try {
      String input1 = "A19A0001";
      List<String> results1 = split(input1);
      for (String result : results1) {
        System.out.println("Rsult1 : " + result);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    // Ex2
    System.out.println("**********************");
    try {
      String input2 = "BB16ZZ0002";
      List<String> results2 = split(input2);
      for (String result : results2) {
        System.out.println("Rsult2 : " + result);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    
    // Ex3:2要素目が3桁(エラー)
    System.out.println("**********************");
    try {
      String input3 = "BB161ZZ0002";
      List<String> results3 = split(input3);
      for (String result : results3) {
        System.out.println("Rsult3 : " + result);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }

  private static List<String> split(String targetCode) throws Exception {
    Pattern pattern = Pattern.compile("^([A-Z]+)([0-9]{2})([A-Z]+)([0-9]+)$");
    Matcher matcher = pattern.matcher(targetCode);
    if (!matcher.matches() || matcher.groupCount() != 4) {
      throw new Exception("Not Supported Code");
    }
    return Arrays.asList(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4));
  }
}

出力結果

**********************
Rsult1 : A
Rsult1 : 19
Rsult1 : A
Rsult1 : 0001
**********************
Rsult2 : BB
Rsult2 : 16
Rsult2 : ZZ
Rsult2 : 0002
**********************
java.lang.Exception: Not Supported Code
    at com.sample.regularex.CodeSplitter.split(CodeSplitter.java:52)
    at com.sample.regularex.CodeSplitter.main(CodeSplitter.java:39)

例3:「key=Value # Comment」形式

プロパティ・ファイル(.properties) の「key=Value(# Comment)」形式を
保存する際に、Javaのデフォルトの標準ライブラリを使うと
「コメントアウト(#)がなくなってまう」などの
問題があるので、自作しようかなーっと思って、その第一段階として
正規表現を使って「key=Value # Comment」形式を検索・パースできるソースを作ってみる

SampleRegularExpression.java

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SampleRegularExpression {

   public static void main(String[] args) {
      show("key1", "key1=value1 # comment1");
      show("sample.key2", " sample.key2 = value2 # comment2 ");
      show("sample.key3", "   sample.key3  =   value3-1.value3-2   #  comment3      ");
   }

   private static void show(String key, String target) {
      String pattern = String.format(
            "[ \\t]*(%s)[ \\t]*=[ \\t]*(.+)[ \\t]*#[ \\t]*(.+)[ \\t]*$",
            key.replace("\\.", "\\\\."));
      Matcher matcher = Pattern.compile(pattern).matcher(target);
      while(matcher.find()) {
          System.out.println(matcher.group(1));
          System.out.println(matcher.group(2));
          System.out.println(matcher.group(3));
      }
   }
}

出力結果

key1
value1 
comment1
sample.key2
value2 
comment2 
sample.key3
value3-1.value3-2    
comment3      

// 余分な空白は含まれるがとりあえずは。。。
// 本当はコメントがある時とない時でも問題なく動作させたいが。。。

参考文献

http://d.hatena.ne.jp/mtoyoshi/20081005/1223186868
http://javamemo.jpn.org/index.php?%5B%5B%C0%B5%B5%AC%C9%BD%B8%BD%5D%5D#content_1_11
http://d.hatena.ne.jp/mmasashi/20091030/1256919089

関連記事

正規表現 ~ 不要文字除去 / 対象文字のみ抽出 ~
https://dk521123.hatenablog.com/entry/2017/01/19/213612
正規表現 ~ 複雑な文字列置き換え ~
https://dk521123.hatenablog.com/entry/2015/04/08/000052
正規表現 ~ 数字/文字の出現回数を数える ~
https://dk521123.hatenablog.com/entry/2016/10/19/004224_1
正規表現 全般
https://dk521123.hatenablog.com/entry/2011/09/10/235712