是否有简单的 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,并且会抓取 Test1Test2World。我不想得到 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));
    }
}

IDEOne Demo

这就是众所周知的 丢弃技术,您可以丢弃所有未捕获的模式并专注于您想要捕获的模式,例如,如果你有:

".*"|'.*'|`.*`|([^\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+"))

Live demo

在以下情况下失败:

  1. 开场白前没有 space。
  2. 收盘价前有一个 space。
  3. 您的输入中存在嵌套或不需要的引号。

因此它仅在 OP 的此类常规输入上正常工作。