是否有简单的 Java Regex (*SKIP)(*F) 替代方案?
Is there a simple Java Regex (*SKIP)(*F) alternative?
我正在 Java 中编写程序,运行 使用正则表达式遇到了一个小问题。我想捕获所有未包含在引号中的内容。我有一个正则表达式模式,right here, but the issue is, it cannot be used in Java. It uses the (*SKIP)(*F)
trick to skip over the ".*"
, and find anything else(using [^\W]
), but as I said, it cannot be used in Java. I have another pattern that is close, but not quite what I need, right here。它会找到前面或后面没有引号的所有内容。那个的问题是,如果我有这样的东西:Test1 "Hello World!" Test2
,并且会抓取 Test1
、Test2
和 World
。我不想得到 World
,因为它在引号中。我想知道的是,是否有可能做我想做的事,如果可以的话如何做。
这些动词是告诉正则表达式引擎(在本例中为 PCRE)您要丢弃这些匹配项的非常有用的方法。
Java 没有这些动词,但您可以在没有动词 (*SKIP)(*F)
的 java 上使用相同的方法,然后捕获您想要的内容...所以您可以使用:
".*"|([^\W]+)
or
".*"|(\w+)
然后从捕获组1中抓取内容
String text = "test1 \"hello world!\" test2";
Pattern ptrn = Pattern.compile("\".*\"|([^\W]+)");
Matcher m = ptrn.matcher(text);
while (m.find()) {
if (m.group(1) != null) {
System.out.println("Text: "+m.group(1));
}
}
这就是众所周知的 丢弃技术,您可以丢弃所有未捕获的模式并专注于您想要捕获的模式,例如,如果你有:
".*"|'.*'|`.*`|([^\W]+)
这将匹配所有模式,但只会捕获最后一个
你必须匹配你想要避免的内容,然后使用捕获组来提取你想要的内容(我认为没有其他方法)。一个方便的模式可以是:
(?:[^\w"]+|"[^"]*")*+(\w+)
那 returns 每个匹配的捕获组 1 中的结果。 demo
注意:如果您想使用该模式进行替换,请将第一部分也放在捕获组中,并以对该组的引用开始替换字符串:
((?:[^\w"]+|"[^"]*")*+)(\w+)
换句话说,将字符串拆分为:(?:[^\w"]+|"[^"]*")+
您可以将 "[^"]*"
更改为 "[^"\]*+(?s:\.[^"\]*)*+"?
以处理引用部分内的转义引号和最终丢失的结束引号。
很遗憾,我还不能对其他帖子发表评论,但如果有多组引号,Federico Piazza 的解决方案就会失败。例如,如果您的文字如下:
String text = "test1 \"hello world!\" test2 \"foobar\" test3";
在这种情况下它会打印
test1
test3
并完全跳过测试 2
改为使用模式
Pattern ptrn = Pattern.compile("\".*?\"|([\w]+)");
?
将导致 .*
运算符是非贪婪的,并找到下一个引用而不是最后一个引用。因此,要从根本上复制他的答案,您可以执行以下操作。
String text = "test1 \"hello world!\" test2 \"foobar\" test3";
Pattern ptrn = Pattern.compile("\".*?\"|([\w]+)");
Matcher m = ptrn.matcher(text);
while (m.find()) {
if (m.group(1) != null) {
System.out.println("Text: "+m.group(1));
}
}
您需要引号外的单词,不包括尾随 spaces:
[^"\s]++((?=\s*"[^\s])|(?=\s*$)|(?=[^"]+\s+"))
在以下情况下失败:
- 开场白前没有 space。
- 收盘价前有一个 space。
- 您的输入中存在嵌套或不需要的引号。
因此它仅在 OP 的此类常规输入上正常工作。
我正在 Java 中编写程序,运行 使用正则表达式遇到了一个小问题。我想捕获所有未包含在引号中的内容。我有一个正则表达式模式,right here, but the issue is, it cannot be used in Java. It uses the (*SKIP)(*F)
trick to skip over the ".*"
, and find anything else(using [^\W]
), but as I said, it cannot be used in Java. I have another pattern that is close, but not quite what I need, right here。它会找到前面或后面没有引号的所有内容。那个的问题是,如果我有这样的东西:Test1 "Hello World!" Test2
,并且会抓取 Test1
、Test2
和 World
。我不想得到 World
,因为它在引号中。我想知道的是,是否有可能做我想做的事,如果可以的话如何做。
这些动词是告诉正则表达式引擎(在本例中为 PCRE)您要丢弃这些匹配项的非常有用的方法。
Java 没有这些动词,但您可以在没有动词 (*SKIP)(*F)
的 java 上使用相同的方法,然后捕获您想要的内容...所以您可以使用:
".*"|([^\W]+)
or
".*"|(\w+)
然后从捕获组1中抓取内容
String text = "test1 \"hello world!\" test2";
Pattern ptrn = Pattern.compile("\".*\"|([^\W]+)");
Matcher m = ptrn.matcher(text);
while (m.find()) {
if (m.group(1) != null) {
System.out.println("Text: "+m.group(1));
}
}
这就是众所周知的 丢弃技术,您可以丢弃所有未捕获的模式并专注于您想要捕获的模式,例如,如果你有:
".*"|'.*'|`.*`|([^\W]+)
这将匹配所有模式,但只会捕获最后一个
你必须匹配你想要避免的内容,然后使用捕获组来提取你想要的内容(我认为没有其他方法)。一个方便的模式可以是:
(?:[^\w"]+|"[^"]*")*+(\w+)
那 returns 每个匹配的捕获组 1 中的结果。 demo
注意:如果您想使用该模式进行替换,请将第一部分也放在捕获组中,并以对该组的引用开始替换字符串:
((?:[^\w"]+|"[^"]*")*+)(\w+)
换句话说,将字符串拆分为:(?:[^\w"]+|"[^"]*")+
您可以将 "[^"]*"
更改为 "[^"\]*+(?s:\.[^"\]*)*+"?
以处理引用部分内的转义引号和最终丢失的结束引号。
很遗憾,我还不能对其他帖子发表评论,但如果有多组引号,Federico Piazza 的解决方案就会失败。例如,如果您的文字如下:
String text = "test1 \"hello world!\" test2 \"foobar\" test3";
在这种情况下它会打印
test1
test3
并完全跳过测试 2
改为使用模式
Pattern ptrn = Pattern.compile("\".*?\"|([\w]+)");
?
将导致 .*
运算符是非贪婪的,并找到下一个引用而不是最后一个引用。因此,要从根本上复制他的答案,您可以执行以下操作。
String text = "test1 \"hello world!\" test2 \"foobar\" test3";
Pattern ptrn = Pattern.compile("\".*?\"|([\w]+)");
Matcher m = ptrn.matcher(text);
while (m.find()) {
if (m.group(1) != null) {
System.out.println("Text: "+m.group(1));
}
}
您需要引号外的单词,不包括尾随 spaces:
[^"\s]++((?=\s*"[^\s])|(?=\s*$)|(?=[^"]+\s+"))
在以下情况下失败:
- 开场白前没有 space。
- 收盘价前有一个 space。
- 您的输入中存在嵌套或不需要的引号。
因此它仅在 OP 的此类常规输入上正常工作。