Java 正则表达式来选择所有不在引号中的空白?

Java 正则表达式来选择所有不在引号中的空白?,java,regex,parsing,Java,Regex,Parsing,我不太擅长正则表达式,有人能给我一个正则表达式在Java中使用,它将选择所有不在两个引号之间的空格吗?我正在尝试从字符串中删除所有此类空格,因此任何这样做的解决方案都会起作用 例如: 这是正则表达式的测试语句 应该成为 这是正则表达式的测试语句 这不是正则表达式所擅长的。用正则表达式搜索和替换函数总是有点受限,任何类型的嵌套/包含都变得困难和/或不可能 我建议另一种方法:在引号字符上拆分字符串。遍历得到的字符串数组,并从每个其他子字符串中去掉空格,不管是以第一个还是第二个开头,这取决于字符串是否

我不太擅长正则表达式,有人能给我一个正则表达式在Java中使用,它将选择所有不在两个引号之间的空格吗?我正在尝试从字符串中删除所有此类空格,因此任何这样做的解决方案都会起作用

例如:

这是正则表达式的测试语句

应该成为

这是正则表达式的测试语句


这不是正则表达式所擅长的。用正则表达式搜索和替换函数总是有点受限,任何类型的嵌套/包含都变得困难和/或不可能

我建议另一种方法:在引号字符上拆分字符串。遍历得到的字符串数组,并从每个其他子字符串中去掉空格,不管是以第一个还是第二个开头,这取决于字符串是否以引号开头。然后使用引号作为分隔符将它们重新连接在一起。这应该会产生你想要的结果

希望有帮助

PS:注意,这不会处理嵌套字符串,但由于不能使用ASCII双qutoe字符生成嵌套字符串,我假设您不需要这种行为


PPS:一旦你处理了你的子字符串,那么现在正是使用正则表达式消除这些空格的好时机——不必担心包含引号。请记住使用/../g修饰符以确保它是全局替换,而不仅仅是第一次匹配。

这不是一个精确的解决方案,但您可以通过执行以下操作来实现您的目标:

步骤1:匹配两段

\\(([a-zA-Z ]\*)"([a-zA-Z ]\*)"\\)
步骤2:删除空格

temp = $1 replace " " with ""
步骤3:重建字符串

(temp"$2")

引号外的空白组由非空白的a或引号内的b分隔

也许是这样的:

(\s+)([^ "]+|"[^"]*")*
第一部分匹配空间序列;第二部分匹配非空格和非引号,或者引号中的某些内容,可以重复任意次数。第二部分是分离器

这将为结果中的每个项目提供两个组;忽略第二个元素。为了谨慎起见,我们需要括号,而不是匹配分组。或者,您可以说,连接所有第二个元素-尽管您也需要匹配第一个非空格单词,或者在本例中,将空格设置为可选:

StringBuffer b = new StringBuffer();
Pattern p = Pattern.compile("(\\s+)?([^ \"]+|\"[^\"]*\")*");
Matcher m = p.matcher("this is \"a test\"");
while (m.find()) {
    if (m.group(2) != null)
        b.append(m.group(2));
}
System.out.println(b.toString());
我在Java中没有做太多的正则表达式,所以希望有bug

最后,如果正则表达式是强制性的,我会这样做-


与Xavier的技术一样,您也可以像在C中那样简单地执行此操作:只需迭代输入字符,并将每个字符复制到新字符串中(如果不是空格,或者在此之前您已经计算了奇数个引号)。

如果只有一组引号,您可以执行以下操作:

    String s = "(this is a test \"sentence for the regex\") a b c";

    Matcher matcher = Pattern.compile("^[^\"]+|[^\"]+$").matcher(s);
    while (matcher.find())
    {
        String group = matcher.group();
        s = s.replace(group, group.replaceAll("\\s", ""));
    }

    System.out.println(s); // (thisisatest"sentence for the regex")abc

这里有一个单一的正则表达式替换:

\s+(?=([^"]*"[^"]*")*[^"]*$)
这将取代:

(this is a test "sentence for the regex" foo bar)
与:

请注意,如果可以转义引号,则更详细的正则表达式将起到以下作用:

\s+(?=((\\[\\"]|[^\\"])*"(\\[\\"]|[^\\"])*")*(\\[\\"]|[^\\"])*$)
它将替换输入:

(this is a test "sentence \"for the regex" foo bar)
与:

注意,它也适用于转义的退格:这是regexfoobar的测试语句\\\

不用说,这真的不应该被用来执行这样的任务:它让人眼睛流血,它在二次时间内执行任务,而存在一个简单的线性解决方案

编辑 快速演示:

String text = "(this is a test \"sentence \\\"for the regex\" foo bar)";
String regex = "\\s+(?=((\\\\[\\\\\"]|[^\\\\\"])*\"(\\\\[\\\\\"]|[^\\\\\"])*\")*(\\\\[\\\\\"]|[^\\\\\"])*$)";
System.out.println(text.replaceAll(regex, ""));

// output: (thisisatest"sentence \"for the regex"foobar)

这里是一个正则表达式,它适用于单引号和双引号,假设所有字符串都被正确分隔

\s+(?=(?:[^\'"]*[\'"][^\'"]*[\'"])*[^\'"]*$)
它无法处理包含引号的字符串


我完全不知道排名靠前的答案是如何工作的,而且正则表达式非常庞大,因此我提交了一个稍微简单一些的答案:

\s+(?=(?:'(?:\\'|[^'])+'|[^'])+$)
理论上,它的工作原理是在测试空白是否是一个有效的破译位置之前,使用一个先行匹配来确保单引号一直平衡到字符串的末尾


这表明它正在执行,确实如此,但速度相当缓慢。正如其他答案可能已经指出的那样,使用这样的表达式来拆分可能引用的字符串就是使用锤子来移除铆钉。在我的例子中,我将这个正则表达式输入到一个程序中,该程序使用正则表达式在fzf上拆分。

是否只有一组引号?因为这不能用于任意数量的引号,至少不能用于正则表达式。如果引号总是平衡的,如果嵌套引号是转义的,则可以这样做。我想知道是否存在这样一个万能的正则表达式。+1是更合理的方法,但我会将其写成s=s.replaceAll\\s+[^\\s\]+\[^\]*\\\\\\\z,$1;。空白并不是真正的可选,关键是要删除它,毕竟,所以你不需要对它进行分组。另一部分也不是可选的,也不需要一次匹配多个部分,所以我去掉了*。我只需要在字符串末尾添加空白的\z替代项。请尝试使用字符串this is a test \ this is a test\。它最终会替换所有的空格,因为replace会全局替换所有看起来像regex匹配的东西。Thi
s的工作原理很棒,但是解释一下它到底是如何工作的会很有帮助。我认为这是我发现的最好的一个。谢谢,它可以完美地作为Supreme的tabalign正则表达式
\s+(?=(?:[^\'"]*[\'"][^\'"]*[\'"])*[^\'"]*$)
\s+(?=(?:'(?:\\'|[^'])+'|[^'])+$)