Как удалить несбалансированные / непарнированные двойные кавычки (на Java) - PullRequest
4 голосов
/ 29 марта 2012

Я думал поделиться этой относительно умной проблемой со всеми здесь.Я пытаюсь удалить несбалансированные / непарные двойные кавычки из строки.

Моя работа в процессе, возможно, я близок к решению.Но я еще не получил рабочее решение. Я не могу удалить непарные / непаренные двойные кавычки из строки.

Пример ввода

string1=injunct! alter ego."
string2=successor "alter ego" single employer"  "proceeding "citation assets"

ВыводДолжно быть

string1=injunct! alter ego.
string2=successor "alter ego" single employer  proceeding "citation assets"

Эта проблема звучит аналогично Использование Java удаляет несбалансированные / непаренные скобки

Вот мой код (пока он не удаляется)все двойные кавычки)

private String removeUnattachedDoubleQuotes(String stringWithDoubleQuotes) {
    String firstPass = "";

    String openingQuotePattern = "\\\"[a-z0-9\\p{Punct}]";
    String closingQuotePattern = "[a-z0-9\\p{Punct}]\\\"";

    int doubleQuoteLevel = 0;
    for (int i = 0; i < stringWithDoubleQuotes.length() - 3; i++) {
        String c = stringWithDoubleQuotes.substring(i, i + 2);
        if (c.matches(openingQuotePattern)) {
            doubleQuoteLevel++;
            firstPass += c;
        }
        else if (c.matches(closingQuotePattern)) {
            if (doubleQuoteLevel > 0) {
                doubleQuoteLevel--;
                firstPass += c;
            }
        }
        else {
            firstPass += c;
        }
    }

    String secondPass = "";
    doubleQuoteLevel = 0;
    for (int i = firstPass.length() - 1; i >= 0; i--) {
        String c = stringWithDoubleQuotes.substring(i, i + 2);
        if (c.matches(closingQuotePattern)) {
            doubleQuoteLevel++;
            secondPass = c + secondPass;
        }
        else if (c.matches(openingQuotePattern)) {
            if (doubleQuoteLevel > 0) {
                doubleQuoteLevel--;
                secondPass = c + secondPass;
            }
        }
        else {
            secondPass = c + secondPass;
        }
    }

    String result = secondPass;

    return result;
}

Ответы [ 2 ]

2 голосов
/ 29 марта 2012

Возможно, это можно сделать в одном регулярном выражении, если нет вложенности.
Существует понятие грубо определенных разделителей, и возможно «смещение»
эти правила, чтобы получить лучший результат.
Все зависит от того, какие правила изложены. Это регулярное выражение учитывает
три возможных сценария в порядке;

  1. Действительная пара
  2. Неверная пара (со смещением)
  3. Неверный одиночный

Он также не анализирует "" после конца строки. Но это действительно несколько
строки объединены в одну строку. Чтобы изменить это, удалите \n там, где вы его видите.


глобальный контекст - необработанное регулярное выражение поиска
укороченный

(?:("[a-zA-Z0-9\p{Punct}][^"\n]*(?<=[a-zA-Z0-9\p{Punct}])")|(?<![a-zA-Z0-9\p{Punct}])"([^"\n]*)"(?![a-zA-Z0-9\p{Punct}])|")

замена группировки

$1$2 or \1\2

Расширенное необработанное регулярное выражение:

(?:                            // Grouping
                                  // Try to line up a valid pair
   (                                 // Capt grp (1) start 
     "                               // "
      [a-zA-Z0-9\p{Punct}]              // 1 of [a-zA-Z0-9\p{Punct}]
      [^"\n]*                           // 0 or more non- [^"\n] characters
      (?<=[a-zA-Z0-9\p{Punct}])         // 1 of [a-zA-Z0-9\p{Punct}] behind us
     "                               // "
   )                                 // End capt grp (1)

  |                               // OR, try to line up an invalid pair
       (?<![a-zA-Z0-9\p{Punct}])     // Bias, not 1 of [a-zA-Z0-9\p{Punct}] behind us
     "                               // "
   (  [^"\n]*  )                        // Capt grp (2) - 0 or more non- [^"\n] characters
     "                               // "
       (?![a-zA-Z0-9\p{Punct}])      // Bias, not 1 of [a-zA-Z0-9\p{Punct}] ahead of us

  |                               // OR, this single " is considered invalid
     "                               // "
)                               // End Grouping

Тестовый Perl (не имеет Java)

$str = '
string1=injunct! alter ego."
string2=successor "alter ego" single employer "a" free" proceeding "citation assets"
';

print "\n'$str'\n";

$str =~ s
/
  (?:
     (
       "[a-zA-Z0-9\p{Punct}]
        [^"\n]*
        (?<=[a-zA-Z0-9\p{Punct}])
       "
     )
   |
       (?<![a-zA-Z0-9\p{Punct}])
       " 
     (  [^"\n]*  )
       " (?![a-zA-Z0-9\p{Punct}])
   |
       "
  )
/$1$2/xg;

print "\n'$str'\n";

Выход

'
string1=injunct! alter ego."
string2=successor "alter ego" single employer "a" free" proceeding "citation assets"
'

'
string1=injunct! alter ego.
string2=successor "alter ego" single employer "a" free proceeding "citation assets"
'
1 голос
/ 29 марта 2012

Вы можете использовать что-то вроде (нотация Perl):

s/("(?=\S)[^"]*(?<=\S)")|"/$1/g;

Что в Java будет:

str.replaceAll("(\"(?=\\S)[^\"]*(?<=\\S)\")|\"", "$1");
...