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
a source to share
(?<=^|[^\\]):
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 :)
a source to share
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.
a source to share