Regex Question - один или несколько пробелов за пределами заключенного в кавычки блока текста - PullRequest
2 голосов
/ 05 ноября 2008

Я хочу заменить любое вхождение более одного пробела одним пробелом, но в кавычках не предпринимать никаких действий в тексте.

Есть ли способ сделать это с помощью регулярного выражения Java? Если да, не могли бы вы попробовать или дать мне подсказку?

Ответы [ 7 ]

4 голосов
/ 05 ноября 2008

Вот еще один подход, который использует прогноз, чтобы определить, что все кавычки после текущей позиции идут в виде совпадающих пар.

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

Если необходимо, указатель может быть адаптирован для обработки экранированных кавычек внутри цитируемых разделов.

2 голосов
/ 05 ноября 2008

При попытке сопоставить что-то, что может содержаться внутри чего-то другого, может быть полезно создать регулярное выражение, которое соответствует обоим, например:

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

Это будет соответствовать строка в кавычках или два или более пробелов. Поскольку два выражения объединены, оно будет соответствовать строке в кавычках ИЛИ двум или более пробелам, но не пробелам в кавычках. Используя это выражение, вам нужно проверить каждое совпадение, чтобы определить, является ли оно строкой в ​​кавычках или двумя или более пробелами, и действовать соответственно:

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 );
0 голосов
/ 05 ноября 2008

Джефф, вы на правильном пути, но в вашем коде есть несколько ошибок, а именно: (1) вы забыли экранировать кавычки внутри отрицательных классов символов; (2) Парены внутри первой группы захвата должны были быть не захватывающего сорта; (3) Если второй набор захватывающих паренов не участвует в матче, group(2) возвращает ноль, и вы не проверяете это; и (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() );
  }
}
0 голосов
/ 05 ноября 2008

После того, как вы проанализируете цитируемый контент, запустите его на остальной части, массово или по кусочкам, если необходимо:

String text = "ABC   DEF GHI   JKL";
text = text.replaceAll("( )+", " ");
// text: "ABC DEF GHI JKL"
0 голосов
/ 05 ноября 2008

Лично я не использую 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
0 голосов
/ 05 ноября 2008

Токенизируйте его и выбрасывайте один пробел между токенами. Быстрый Google для "Java Tokenizer, который обрабатывает кавычки" появился: эта ссылка

YMMV

edit: ТАК не понравилась эта ссылка. Вот ссылка для поиска в Google: google . Это был первый результат.

0 голосов
/ 05 ноября 2008

текст между кавычками: находятся ли кавычки в одной или нескольких строках?

...