【Java】正規表現 ~ 複雑な文字列置き換え ~

■ はじめに

今回は、Javaの replaceFirst / replaceAll を使って
複雑な文字列置き換えを行う。

【1】複雑な文字列置き換え

1)replaceFirst / replaceAll

* 正規表現を使って、文字列置き換えることにより、複雑な処理が可能になる
* replaceAll()は、不要文字除去 / 対象文字のみ抽出にも使える。
 詳細は以下の関連記事を参照のこと。

https://dk521123.hatenablog.com/entry/2017/01/19/213612

2)補足:replaceLast() について

* replaceFirst があるのに、replaceLast は標準ではない
* 自作した場合は以下(ただし、使い方に注意)

サンプル
http://stackoverflow.com/questions/2282728/java-replacelast

import java.text.MessageFormat;

public class Replacer {
  private static final String FORMAT_FOR_REPLACE_LAST = "(?s){0}(?!.*?{0})";

  public static void main(String[] args) {
    System.out.println(replaceLast("サーバー", "ー", ""));
    System.out.println(replaceLast("サーバ", "ー", ""));
  }

  public static String replaceLast(String textValue, String regex, String replacement) {
    if (textValue == null) {
      return null;
    }
    return textValue.replaceFirst(MessageFormat.format(FORMAT_FOR_REPLACE_LAST, regex), replacement);
  }
}

出力結果

サーバ
サバ

※どちらも「サーバ」としたい場合、以下の関連記事を参照のこと

https://dk521123.hatenablog.com/entry/2017/01/19/213612

【2】サンプル

例1:拡張子の変換

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

public class SampleExtenstion {

   public static void main(String[] args) {
      String outoutFileName = 
            SampleExtenstion.getTextReplacedExtension(
                  "test.sample.csv", "csv", ".java");
      System.out.println("Result " + outoutFileName);
   }
   private static String getTextReplacedExtension(
         String targetToReplace, String targetExtension, String replacedExtension) {
      Pattern pattern = Pattern.compile(String.format("\\.%s$", targetExtension));
      Matcher matcher = pattern.matcher(targetToReplace);
      return matcher.replaceAll(replacedExtension);
   }
}

出力結果

Result test.sample.java

参考文献
http://www.javadrive.jp/regex/replace/index3.html
http://doc.mas3.net/regexp/replace.html#tail

例2:XXX を置き換える

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

public class Main {
   public static void main(String[] args) {
      String before = "<?xml version=\"1.0\"><user><id>id</id><pw>password</pw></user>";
      String regex = "<pw>.*</pw>";
      Pattern pattern = Pattern.compile(regex);

      Matcher matcher = pattern.matcher(before);
      String after = matcher.replaceFirst("<pw>???</pw>");

      System.out.println("Before : " + before);
      System.out.println("After  : " + after);
   }
}

出力結果

Before : <?xml version="1.0"><user><id>id</id><pw>password</pw></user>
After  : <?xml version="1.0"><user><id>id</id><pw>???</pw></user>

補足:「.*」について

* 「.*」 = 0文字以上の任意の文字列

例3<nsXX:pw>YYY</nsXX:pw> を置き換える

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

public class Main {
   public static void main(String[] args) {
      String before = "<?xml version=\"1.0\"><ns10:user><ns10:id>id</ns10:id><ns10:pw>password</ns10:pw></ns10:user>";
      String regex = "<ns([0-9]*):pw>.*</ns([0-9]*):pw>";
      Pattern pattern = Pattern.compile(regex);

      Matcher matcher = pattern.matcher(before);
      String after = matcher.replaceFirst("<ns$1:pw>???</ns$2:pw>");

      System.out.println("Before : " + before);
      System.out.println("After  : " + after);
   }
}

出力結果

Before : <?xml version="1.0"><ns10:user><ns10:id>id</ns10:id><ns10:pw>password</ns10:pw></ns10:user>
After  : <?xml version="1.0"><ns10:user><ns10:id>id</ns10:id><ns10:pw>???</ns10:pw></ns10:user>

参考文献

replaceFirst / replaceAll
http://www.javadrive.jp/regex/replace/index1.html
正規表現
http://java-reference.sakuraweb.com/java_string_regex.html
https://www.mlab.im.dendai.ac.jp/~yamada/java/regex/
グルーピング
http://www.javadrive.jp/regex/replace/index2.html
http://unageanu.hatenablog.com/entry/20090223/1235392085
http://haljik.hatenablog.com/entry/20080513/1210676911

関連記事

正規表現 ~ 文字列の抽出 ~
https://dk521123.hatenablog.com/entry/2016/12/30/142128
正規表現 ~ 不要文字除去 / 対象文字のみ抽出 ~
https://dk521123.hatenablog.com/entry/2017/01/19/213612
正規表現 ~ 数字/文字の出現回数を数える ~
https://dk521123.hatenablog.com/entry/2016/10/19/004224_1
パス・ファイルの扱い
https://dk521123.hatenablog.com/entry/2010/01/12/091848
正規表現 全般
https://dk521123.hatenablog.com/entry/2011/09/10/235712