我有点卡住了,试图想出正则表达式来分解具有以下属性的字符串:
- 由 | 分隔(管道)字符
- 如果单个值包含管道,则使用\(反斜杠)转义
- 如果单个值以反斜杠结尾,则用反斜杠转义
例如,这里有一些我想分解的字符串:
One|Two|Three
应该产生:["One", "Two", "Three"]
One\|Two\|Three
应该产生:["One|Two|Three"]
One\\|Two\|Three
应该产生:["One\", "Two|Three"]
现在我怎么能用一个正则表达式把它分开呢?
更新:正如你们中的许多人所建议的,这不是正则表达式的良好应用。此外,正则表达式解决方案比仅遍历字符慢几个数量级。我最终遍历了字符:
public static List<String> splitValues(String val) {
final List<String> list = new ArrayList<String>();
boolean esc = false;
final StringBuilder sb = new StringBuilder(1024);
final CharacterIterator it = new StringCharacterIterator(val);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if(esc) {
sb.append(c);
esc = false;
} else if(c == '\\') {
esc = true;
} else if(c == '|') {
list.add(sb.toString());
sb.delete(0, sb.length());
} else {
sb.append(c);
}
}
if(sb.length() > 0) {
list.add(sb.toString());
}
return list;
}
最佳答案
技巧是不要使用 split()
方法。这迫使您使用后视来检测转义字符,但是当转义本身被转义时(正如您所发现的那样),它会失败。您需要使用 find()
来匹配 tokens 而不是分隔符:
public static List<String> splitIt(String source)
{
Pattern p = Pattern.compile("(?:[^|\\\\]|\\\\.)+");
Matcher m = p.matcher(source);
List<String> result = new ArrayList<String>();
while (m.find())
{
result.add(m.group().replaceAll("\\\\(.)", "$1"));
}
return result;
}
public static void main(String[] args) throws Exception
{
String[] test = { "One|Two|Three",
"One\\|Two\\|Three",
"One\\\\|Two\\|Three",
"One\\\\\\|Two" };
for (String s :test)
{
System.out.printf("%n%s%n%s%n", s, splitIt(s));
}
}
输出:
One|Two|Three
[One, Two, Three]
One\|Two\|Three
[One|Two|Three]
One\\|Two\|Three
[One\, Two|Three]
One\\\|Two
[One\|Two]
关于java正则表达式拆分字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6879610/