2

我想用一个空格替换任何出现的多个空格,但在引号之间的文本中不采取任何操作。

有没有办法用 Java 正则表达式做到这一点?如果是这样,您可以尝试一下或给我一个提示吗?

4

7 回答 7

4

这是另一种方法,它使用前瞻来确定当前位置之后的所有引号都成对出现。

text = text.replaceAll("  ++(?=(?:[^\"]*+\"[^\"]*+\")*+[^\"]*+$)", " ");

如果需要,可以调整前瞻以处理引用部分内的转义引号。

于 2008-11-05T06:42:29.427 回答
2

当尝试匹配可以包含在其他内容中的内容时,构造一个匹配两者的正则表达式会很有帮助,如下所示:

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

这将匹配带引号的字符串或两个或多个空格。因为这两个表达式组合在一起,所以它将匹配带引号的字符串或两个或多个空格,但不匹配引号内的空格。使用此表达式,您将需要检查每个匹配项以确定它是带引号的字符串还是两个或多个空格并采取相应的措施:

Pattern spaceOrStringRegex = Pattern.compile( "(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(  +)" );

StringBuffer replacementBuffer = new StringBuffer();

Matcher spaceOrStringMatcher = spaceOrStringRegex.matcher( text );

while ( spaceOrStringMatcher.find() ) 
{
    // if the space group is the match
    if ( spaceOrStringMatcher.group( 2 ) != null ) 
    {
        // replace with a single space
        spaceOrStringMatcher.appendReplacement( replacementBuffer, " " );
    }
}

spaceOrStringMatcher.appendTail( replacementBuffer );
于 2008-11-05T00:54:02.860 回答
0

引号之间的文字:引号是在同一行还是多行?

于 2008-11-05T00:44:27.387 回答
0

标记它并在标记之间发出一个空格。“处理引号的java标记器”的快速谷歌出现了: 这个链接

YMMV

编辑:所以不喜欢那个链接。这是谷歌搜索链接:google。这是第一个结果。

于 2008-11-05T00:58:29.230 回答
0

就个人而言,我不使用 Java,但这个 RegExp 可以解决问题:

([^\" ])*(\\\".*?\\\")*

尝试使用 RegExBuddy 的表达式,它会生成此代码,对我来说看起来不错:

try {
    Pattern regex = Pattern.compile("([^\" ])*(\\\".*?\\\")*", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
    Matcher regexMatcher = regex.matcher(subjectString);
    while (regexMatcher.find()) {
        for (int i = 1; i <= regexMatcher.groupCount(); i++) {
            // matched text: regexMatcher.group(i)
            // match start: regexMatcher.start(i)
            // match end: regexMatcher.end(i)

            // I suppose here you must use something like
            // sstr += regexMatcher.group(i) + " "
        }
    }
} catch (PatternSyntaxException ex) {
    // Syntax error in the regular expression
}

至少,它似乎在 Python 中运行良好:

import re

text = """
este  es   un texto de   prueba "para ver  como se comporta  " la funcion   sobre esto
"para ver  como se comporta  " la funcion   sobre esto  "o sobre otro" lo q sea
"""

ret = ""
print text  

reobj = re.compile(r'([^\" ])*(\".*?\")*', re.IGNORECASE)

for match in reobj.finditer(text):
    if match.group() <> "":
        ret = ret + match.group() + "|"

print ret
于 2008-11-05T01:28:40.077 回答
0

解析出引用的内容后,根据需要在其余部分上批量或逐个运行:

String text = "ABC   DEF GHI   JKL";
text = text.replaceAll("( )+", " ");
// text: "ABC DEF GHI JKL"
于 2008-11-05T05:12:24.163 回答
0

杰夫,你在正确的轨道上,但你的代码中有一些错误,也就是说:(1)你忘记在否定字符类中转义引号;(2)第一个捕获组内的parens应该是非捕获品种;(3) 如果第二组捕获括号不参与匹配,则group(2)返回 null,并且您没有对此进行测试;(4) 如果您在正则表达式中测试两个或多个空格而不是一个或多个,则无需稍后检查匹配的长度。这是修改后的代码:

import java.util.regex.*;

public class Test
{
  public static void main(String[] args) throws Exception
  {
    String text = "blah    blah  \"boo   boo boo\"  blah  blah";
    Pattern p = Pattern.compile( "(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")|(  +)" );
    StringBuffer sb = new StringBuffer();
    Matcher m = p.matcher( text );
    while ( m.find() ) 
    {
      if ( m.group( 2 ) != null ) 
      {
        m.appendReplacement( sb, " " );
      }
    }
    m.appendTail( sb );
    System.out.println( sb.toString() );
  }
}
于 2008-11-05T06:14:35.427 回答