Splitting a string (especially in Java with java.util.regex or whatever)

Does anyone know how to split a string into a character given its escape sequence?

For example, if the character ":", "a: b" is split into two parts ("a" and "b"), while "a: b" is not split at all.

I think this is difficult (impossible?) To do with regular expressions.

Thanks in advance,

Kedar

+1


a source to share


2 answers


(?<=^|[^\\]):

brings you closer, but doesn't address escaped slashes. (This is a literal regex, of course you must escape the forward slash in it to get it into a java string)

(?<=(^|[^\\])(\\\\)*):

How about this? I think this should satisfy any ":" that is preceded by an even number of forward slashes.



Edit: don't vote. MizardX is better :)

+2


a source


Since Java supports variable length hovers (while they are finite), you can do it like this:

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})

    looks behind an even number of backslashes (including zero, up to a maximum of 10).

Output:

Input string: foo:bar\:baz\\:qux\\\:quux\\\\:corge


Part 1: foo


Part 2: bar\:baz\\


Part 3: qux\\\:quux\\\\


Part 4: corge



Another way would be to match the parts themselves rather than splitting on delimiters.

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));
}

      

The weird syntax stems from the fact that it needs to handle the case of empty shapes at the beginning and end of a line. When the match has exactly zero characters, the next attempt will start one character past its end. If it weren't, it would match another blank line and another, ad infinitum & hellip;

  • (?<=\A|\G:)

    will look like the beginning of the line (first part) and the end of the previous match followed by a separator. If we did (?:\A|\G:)

    , it won't work if the first part is empty (input starts with a separator).
  • \\.

    matches any escaped character.
  • [^:\\]

    matches any character that is not escaped (because it \\.

    consumes both of them).
  • ((?:\\.|[^:\\])*)

    captures all characters up to the first unexperienced separator into capture group 1.
+2


a source







All Articles