我有一个字符串,我需要根据空格和完全匹配的引号进行拆分。
如果
string = "It is fun \"to write\" regular\"expression"
分裂后,我希望结果为:
它
是
乐趣
"写"
定期
"表达
我接近这样做的正则表达式是:
STRING_SPLIT_REGEXP = "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'"
提前感谢您的回答。
答案 0 :(得分:2)
您似乎只使用了来自this answer的正则表达式,但正如您所看到的那样,它不使用split
类中的find
而是Matcher
方法。此答案还会处理'
,您的输入显示没有任何迹象。
因此,您可以通过删除处理'
的部件来改进此正则表达式,这将使其看起来像
[^\\s\"]+|\"([^\"]*)\"
此外,由于您希望将"
作为令牌的一部分包含在内,因此您无需将"
之间的匹配放在单独的组中,因此请删除\"([^\"]*)\"
部分中的括号
[^\\s\"]+|\"[^\"]*\"
现在您需要做的就是添加不会关闭"
的情况,但您将获得字符串结尾。所以将此正则表达式更改为
[^\\s\"]+|\"[^\"]*(\"|$)
在此之后你可以使用匹配器,find
所有存储令牌,让我们在List
中说。
示例:
String data = "It is fun \"to write\" regular\"expression";
List<String> matchList = new ArrayList<String>();
Pattern regex = Pattern.compile("[^\\s\"]+|\"[^\"]*(\"|$)");
Matcher regexMatcher = regex.matcher(data);
while (regexMatcher.find()) {
System.out.println(regexMatcher.group());
matchList.add(regexMatcher.group());
}
输出:
It
is
fun
"to write"
regular
"expression
处理此数据的更复杂表达式可能看起来像
String data = "It is fun \"to write\" regular \"expression";
for(String s : data.split("(?<!\\G)(?<=\\G[^\"]*(\"[^\"]{0,100000}\")?[^\"]*)((?<=\"(?!\\s))|\\s+|(?=\"))"))
System.out.println(s);
但是这种方法过于复杂,然后编写自己的解析器。
这样的解析器可能看起来像
public static List<String> parse(String data) {
List<String> tokens = new ArrayList<String>();
StringBuilder sb = new StringBuilder();
boolean insideQuote = false;
char previous = '\0';
for (char ch : data.toCharArray()) {
if (ch == ' ' && !insideQuote) {
if (sb.length() > 0 && previous != '"')
addTokenAndResetBuilder(sb, tokens);
} else if (ch == '"') {
if (insideQuote) {
sb.append(ch);
addTokenAndResetBuilder(sb, tokens);
} else {
addTokenAndResetBuilder(sb, tokens);
sb.append(ch);
}
insideQuote = !insideQuote;
} else {
sb.append(ch);
}
previous = ch;
}
addTokenAndResetBuilder(sb, tokens);
return tokens;
}
private static void addTokenAndResetBuilder(StringBuilder sb, List<String> list) {
if (sb.length() > 0) {
list.add(sb.toString());
sb.delete(0, sb.length());
}
}
用法
String data = "It is fun \"to write\" regular\"expression\"xxx\"yyy";
for (String s : parse(data))
System.out.println(s);
答案 1 :(得分:1)
这里遇到正则表达式的基本限制。一般来说,他们无法检测递归,深度等。
所以在你的字符串中:
"It is fun \"to write\" regular\"expression"
to
和write
之间的空格以及\"
和regular
之间的空格都在引号内。正则表达式无法计算&#34;引用数量灵活,并根据它采取行动。
您需要为此编写自己的字符串解析器(或使用现有的字符串解析器)。但正则表达式无法处理它。
答案 2 :(得分:1)
诀窍是使用灵活的前瞻来断言:
我把它弄成了一行,但它是一个巨大的:
String[] parts = str.split("(\\s+|(?<!\\s)(?=\"))(?=(([^\"]*\"){2})*[^\"]*"
+ (str.matches("(([^\"]*\"){2})*[^\"]*") ? "" : "\"[^\"]*") + "$)");
这正确地将示例字符串拆分为带有或不带的尾随引号(无论尾部术语是否包含空格)。