技術共有

正規表現で?

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

正規表現では?これは、{0, 1} に相当する 0 または 1 倍の量を表すことができ、また、他の意味を表す特殊文字として使用することもできます。

貪欲でないマッチング

? に続く他の数量修飾子は、非貪欲一致、つまり、検索される可能な限り短い文字列との一致を示します。

例を見てみましょう:

  1. @Test
  2. public void test() {
  3. Pattern pattern = Pattern.compile("a.*?");
  4. Matcher matcher = pattern.matcher("abcabc");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. }
  8. }

実行後の出力: abcabc

最短試合じゃないですか?なぜ失敗したのでしょうか?

これには実際には、非貪欲一致のルールが含まれます。非貪欲マッチングの場合、次のルールの前に最短パスがマッチングされます。次のルールがない場合は貪欲マッチングとして処理されます。

つまり、「a.*?」のみが出現した場合でも貪欲一致に従って処理されます。

正しい使用法を見てみましょう。

  1. @Test
  2. public void test() {
  3. Pattern pattern = Pattern.compile("(a.*?)(.*)");
  4. Matcher matcher = pattern.matcher("afcafc");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group(0));
  7. System.out.println(matcher.group(1));
  8. System.out.println(matcher.group(2));
  9. }
  10. }

実行後の出力:

  1. afcafc
  2. a
  3. fcafc

ご覧のとおり、最初のキャプチャ グループは最短の文字列「a」をキャプチャし、2 番目のキャプチャ グループは「fcafc」をキャプチャします。

他の 2 つの状況を見てみましょう。

  • "(a.*)(.*)" 最初のキャプチャ グループはすべてをキャプチャしますが、2 番目のキャプチャ グループはエラーを報告しませんが、何もキャプチャしません。
  • "(a.*?)(.*?)" 最初のキャプチャ グループは "a" をキャプチャし、2 番目のキャプチャ グループは "fcafc" をキャプチャします。後は他にルールがないため、貪欲一致に従って処理されます。 。

一致するがキャプチャされない (?:パターン)

キャプチャ グループで使用する場合、?: は正規表現の前に配置され、一致するがキャプチャされないことを示します。つまり、この一致する値のグループはグループ メソッドでは取得できません。

例を見てみましょう

  1. @Test
  2. public void test0() {
  3. Pattern pattern = Pattern.compile("\d{4}-(?:[a-z]+)");
  4. Matcher matcher = pattern.matcher("3214-opo");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. System.out.println(matcher.group(1)); // 报错
  8. }
  9. }

group(1) を介してキャプチャすると、エラーが報告されます。つまり、一致することはできますが、キャプチャできないということです。 ?: を削除すると、group(1) を通じて正常にキャプチャできます。

単一行モードを有効にする (?s)

(?s) は、右側で単一行モードをオンにし、 . を改行文字 n を含む任意の文字と一致させます。

例を見てみましょう:

  1. private static final String DEFAULT_VARIABLE_PATTERN = "((?s).*)";
  2. /**
  3. * 从输出结果可知,匹配到了换行符 'n'
  4. */
  5. @Test
  6. public void test4() {
  7. Pattern pattern = Pattern.compile(DEFAULT_VARIABLE_PATTERN);
  8. Matcher matcher = pattern.matcher("abcnsdf");
  9. if (matcher.matches()) {
  10. System.out.println(matcher.group());
  11. System.out.println(matcher.group(1));
  12. System.out.println(matcher.group(2)); // (?s) 不能作为捕获组,报错
  13. }
  14. }

キャプチャする場合、(?s) をキャプチャ グループとしてキャプチャすることはできないため、「((?s).*)」でキャプチャできるのは最大でも group(1) であり、group(2) をキャプチャするときにエラーが報告されます。

  1. @Test
  2. public void test5() {
  3. Pattern pattern = Pattern.compile("(.*)");
  4. Matcher matcher = pattern.matcher("abcnsdf");
  5. if (matcher.matches()) {
  6. System.out.println(matcher.group());
  7. System.out.println(matcher.group(1));
  8. }
  9. }

(?s) を削除した後、「abcnsdf」と照合してみます。改行文字があるため、照合が完了せず、何も出力されません。