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

StackOverflow https://stackoverflow.com/questions/263985

  •  06-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

Обозначьте его и выделите один пробел между токенами.Появился быстрый поиск в Google "java tokenizer, который обрабатывает кавычки":эта ссылка

YMMV

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

Лично я не использую 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

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

String text = "ABC   DEF GHI   JKL";
text = text.replaceAll("( )+", " ");
// text: "ABC DEF GHI JKL"

Джефф, ты на правильном пути, но в твоем коде есть несколько ошибок, чтобы: 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() );
  }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top