有一个简单的Java Regex(* SKIP)(* F)替代方案吗?

时间:2016-07-05 21:17:51

标签: java regex regex-negation

我正在用Java编写程序,并且使用正则表达式遇到了一个小问题。我想要捕获未用引号括起来的所有内容。我有一个正则表达式,right here,但问题是,它不能在Java中使用。它使用(*SKIP)(*F)技巧跳过".*",并找到其他任何内容(使用[^\W]),但正如我所说,它不能在Java中使用。我有另一种模式,但不是我需要的,right here。它会在它前面或后面找到没有引号的所有内容。这个问题是,如果我有这样的话:Test1 "Hello World!" Test2,并且会抓住Test1Test2World。我不想获得World,因为它在引号中。我想知道的是,是否有可能做我想做的事情,如果是这样的话。

4 个答案:

答案 0 :(得分:1)

您必须匹配您想要避免的内容并使用捕获组来提取您想要的内容(我不认为还有其他方式)。一个方便的模式可以是:

(?:[^\w"]+|"[^"]*")*+(\w+)

为每个匹配返回捕获组1中的结果。 demo

注意:如果您想使用模式进行替换,请将第一部分放在捕获组中,并使用对该组的引用来启动替换字符串:

((?:[^\w"]+|"[^"]*")*+)(\w+)

其他方式,将您的字符串拆分为:(?:[^\w"]+|"[^"]*")+

您可以将"[^"]*"更改为"[^"\\]*+(?s:\\.[^"\\]*)*+"?以处理引用部分内的转义引号以及最终丢失的结束引用。

答案 1 :(得分:1)

不幸的是我还不能对其他帖子发表评论,但如果有多组报价,Federico Piazza的解决方案将会失败。例如,如果您的文字如下:

String text = "test1 \"hello world!\" test2 \"foobar\" test3";

在这种情况下,它会打印

test1
test3

并完全跳过test2

而是使用模式

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));
    }
}

答案 2 :(得分:0)

这些动词是告诉正则表达式引擎(在这种情况下为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

这就是众所周知的 discard technique ,您可以放弃所有未捕获的模式并专注于您要捕获的模式,例如,如果您有:

".*"|'.*'|`.*`|([^\W]+)

这将匹配所有模式,但会捕获最后一个

Regular expression visualization

答案 3 :(得分:0)

你想要在引号之外的单词排除尾随空格:

[^"\s]++((?=\s*"[^\s])|(?=\s*$)|(?=[^"]+\s+"))

Live demo

如果出现以下情况则失败:

  1. 开场报价前没有空格。
  2. 收盘前有一个空格。
  3. 您的输入中有嵌套或不需要的引号。
  4. 因此它仅定期在OP的常规输入上工作。