【发布时间】:2015-02-03 02:32:23
【问题描述】:
我想从自定义键值协议中解析一个数组。看起来是这样的
RESPONSE GAMEINFO OK
NAME: "gamelobby"
PLAYERS: "alice", "bob", "hodor"
FLAGS: 1, 2, 3
在 Java 中,字符串看起来像这样(它使用 CRLF 作为换行符):
RESPONSE GAMEINFO OK\\r\\nNAME: \"gamelobby\"\\r\\nPLAYERS: \"alice\", \"bob\", \"hodor\"FLAGS: 1, 2, 3\\r\\n
我想按原样捕获"alice", "bob", "hodor"。所以我使用了这个正则表达式,它在 Sublime Text 和 regex101.com 上进行了测试(键不区分大小写)
(?<=(?i:PLAYERS): )([A-Za-z0-9\s\.,:;\?!\n"_-]*)(?=\r\n)
这是来自 Sublime Text 的截图(注意:我在这里省略了 \r):
当我尝试捕获该组时,我也得到了下一行:
Pattern p = Pattern.compile("(?<=(?i:"+key+"): )([A-Za-z0-9\\s\\.,:;\\?!\\n\"_-]*)(?=\\r\\n)");
Matcher matcher = p.matcher(message);
matcher.find();
String value = new String();
try {
value = matcher.group(); // = "\"alice\", \"bob\", \"hodor\"\\r\\nFLAGS: 1, 2, 3"
} ...
注意:\" 或 \\\" 似乎没有区别。
为什么FLAGS: 1, 2, 3 被捕获到\\r\\n,而不是在上面的行中?积极的后视和前瞻可能吗?首先评估哪个前瞻/后视?
编辑:字符串数组的定义是
values = string*("," WSP string)
string = DQUOTE *(ALPHA / DIGIT / WSP / punctuation / "\n") DQUOTE
punctuation = "." / ":" / "," / ";" / "?" / "!" / "-" / "_"
【问题讨论】:
-
它在 SublimeText 中有效,因为最后一行没有新行,而您在 Java 中的输入有。如果您可以假设新行永远不会出现在
PLAYERS行中,那么您应该从您的正则表达式中删除\s和\n,如果您使用的是Java 8,则可能替换为\h。 -
我不能假设,我捕获下一行的核心问题仍然存在
-
所以你不能假设 PLAYER 字段永远不能跨越 2 行或更多?那么,解析它将是一项艰巨的任务。有了这个假设,您可以只拆分输入并逐行解析。
-
对于昵称限制存在(字母数字),我可以在这个例子中假设它。尽管如此,该协议允许使用
\n进行换行的字符串,并且也允许使用字符串数组。 -
也许我误解了一些东西,但你不能在括号表达式上使用非贪婪乘数吗?见regex101.com/r/hN6nB5/1
标签: java regex lookahead lookbehind