1

エスケープシーケンスを考慮して文字列を分割する方法を知っている人はいますか?

たとえば、文字が「:」の場合、「a:b」は 2 つの部分 (「a」と「b」) に分割されますが、「a:b」はまったく分割されません。

これは正規表現では難しい(無理?)と思います。

前もって感謝します、

ケダル

4

2 に答える 2

2

(?<=^|[^\\]):近づきますが、エスケープされたスラッシュには対処しません。(これは文字通りの正規表現です。もちろん、スラッシュをエスケープして Java 文字列にする必要があります)

(?<=(^|[^\\])(\\\\)*): どのようにそのことについて?偶数のスラッシュが前にある「:」を満たす必要があると思います。

編集:これに投票しないでください。MizardXのソリューションの方が優れています:)

于 2009-05-07T19:11:21.760 に答える
2

Java は可変長の後読みをサポートしているため (有限である限り)、次のようにすることができます。

import java.util.regex.*;

public class RegexTest {
    public static void main(String[] argv) {

        Pattern p = Pattern.compile("(?<=(?<!\\\\)(?:\\\\\\\\){0,10}):");

        String text = "foo:bar\\:baz\\\\:qux\\\\\\:quux\\\\\\\\:corge";

        String[] parts = p.split(text);

        System.out.printf("Input string: %s\n", text);
        for (int i = 0; i < parts.length; i++) {
            System.out.printf("Part %d: %s\n", i+1, parts[i]);
        }

    }
}
  • (?<=(?<!\\)(?:\\\\){0,10})偶数個のバックスラッシュ (ゼロを含み、最大 10 個まで) を後ろから探します。

出力:

Input string: foo:bar\:baz\\:qux\\\:quux\\\\:corge
Part 1: foo
Part 2: bar\:baz\\
Part 3: qux\\\:quux\\\\
Part 4: corge

別の方法は、区切り文字で分割するのではなく、パーツ自体を一致させることです。

Pattern p2 = Pattern.compile("(?<=\\A|\\G:)((?:\\\\.|[^:\\\\])*)");
List<String> parts2 = new LinkedList<String>();
Matcher m = p2.matcher(text);
while (m.find()) {
    parts2.add(m.group(1));
}

奇妙な構文は、文字列の最初と最後にある空の部分の大文字と小文字を区別する必要があることに由来します。一致が正確に 0 文字にまたがる場合、次の試行はその末尾の 1 文字を超えて開始されます。そうでない場合は、別の空の文字列と一致し、別の、無限に…

  • (?<=\A|\G:)文字列の先頭 (最初の部分) または前の一致の末尾のいずれかを探し、その後に区切り文字が続きます。を行った(?:\A|\G:)場合、最初のピースが空の場合は失敗します (入力はセパレーターで始まります)。
  • \\.エスケープされた任意の文字に一致します。
  • [^:\\]エスケープ シーケンスに含まれていない任意の文字に一致します (\\.これらの両方が消費されるため)。
  • ((?:\\.|[^:\\])*)最初のエスケープされていない区切り文字までのすべての文字をキャプチャ グループ 1 にキャプチャします。
于 2009-05-07T19:24:54.863 に答える