2013-04-02 1 views
1

Я пытаюсь написать регулярное выражение, которое ищет все ';' символов, за которыми не следует символ NEW LINE (\ n).Регулярное выражение без функции LookBehind

;(?!\\\n) 

и все символы NEW LINE (\ n), которым не предшествует символ ';' Характер:

(?< !;)\\\n 

К сожалению, я использую Qt 4.7.4 QRegExp и он не поддерживает «Смотри позади». Как переписать регулярное выражение выше, чтобы он не использовал «Look Behind»?

ответ

1

Цитирование из документации:

http://doc.qt.digia.com/4.7/qregexp.html#details

И нулевые ширина положительных и нулевой ширина отрицательных условных выражений (? = Шаблон) и (?! Шаблон) поддерживается с тем же синтаксисом, Perl.

Что, вероятно, происходит то, что вы работаете на машине Windows, которая вставлена ​​\r\n, а не просто \n ... или, может быть, это был текстовый файл, созданный на окна машины.

Одна вещь, которой нужно следить за тем, что я обнаружил для lookbehinds, заключается в том, что вы не можете иметь переменную длину lookbehind с большинством обработчиков регулярных выражений.

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

С code-examples section из документации он имеет это:

str = "Nokia Corporation\tqt.nokia.com\tNorway"; 
QString company, web, country; 
rx.setPattern("^([^\t]+)\t([^\t]+)\t([^\t]+)$"); 
if (rx.indexIn(str) != -1) { 
    company = rx.cap(1); 
    web = rx.cap(2); 
    country = rx.cap(3); 
} 

группа захвата определяется с помощью круглых скобках, а позже доступ по его индексу, начиная с 1. индекс является нулевым весь матч (не разбиты на группы захвата).

http://doc.qt.digia.com/4.7/qregexp.html#cap

http://doc.qt.digia.com/4.7/qregexp.html#capturedTexts

Надежда, что помогает. Регулярные выражения могут быть очень забавными, когда они работают правильно. Удачи.

Мне также нравится используя tool. Форматирование может немного отличаться от QRegEx, но довольно быстро переводить и тестировать, как только вы его получите.

UPDATE: Вот полный набор, показывая 4 различных строк захвата и то, что они находят с QRegEx:

#include <QCoreApplication> 
#include <QRegExp> 
#include <QString> 
#include <QDebug> 
#include <QStringList> 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    QString str = 
      "This is a long string;\n" 
      "with some semi colons;\n" 
      "sometimes followed by a new line;\n" 
      "and other times followed; by something else.\n" 

      "(;)([^\\n]) find a semicolon and a new line\n" 
      "(;)(?!\\n) find a semicolon not followed by a new line, negative look-ahead\n" 

      "([^;])(\\n) find a non semicolon and a new line\n" 
      "(?<!;)(\\n) find a new line, not preceeded by a semicolon.\n"; 

    QList <QRegExp> rx_list; 

    QRegExp rx_colon_and_non_newline; 
    rx_colon_and_non_newline.setPattern("(;)([^\\n])"); 

    QRegExp rx_colon_and_neg_lookahead; 
    rx_colon_and_neg_lookahead.setPattern("(;)(?!\\n)"); 

    QRegExp rx_non_colon_and_newline; 
    rx_non_colon_and_newline.setPattern("([^;])(\\n)"); 

    QRegExp rx_neg_lookbehind_and_newline; 
    rx_neg_lookbehind_and_newline.setPattern("(?<!;)(\\n)"); 

    rx_list << rx_colon_and_non_newline 
      << rx_colon_and_neg_lookahead 
      << rx_non_colon_and_newline 
      << rx_neg_lookbehind_and_newline; 

    foreach(QRegExp rx, rx_list) 
    { 
     int count = 0; 
     int pos = 0; 
     qDebug() << "Pattern" << rx.pattern(); 
     while ((pos = rx.indexIn(str, pos)) != -1) { 
      QStringList capturedTexts(rx.capturedTexts()); 

      for(int i = 0; i<capturedTexts.size(); i++) 
       capturedTexts[i].replace('\n',"\\n"); 

      qDebug() << "\t" << count << "Found at position" << pos << capturedTexts; 
      // qDebug() << rx.cap(); 
      pos += rx.matchedLength(); 
      ++count; 
     } 
     if(count == 0) 
      qDebug() << "\tNo matches found."; 
    } 


    return a.exec(); 
} 

выход:

Pattern "(;)([^\n])" 
     0 Found at position 104 ("; ", ";", " ") 
     1 Found at position 126 (";)", ";", ")") 
     2 Found at position 169 (";)", ";", ")") 
     3 Found at position 247 (";]", ";", "]") 
     4 Found at position 295 (";)", ";", ")") 
Pattern "(;)(?!\n)" 
     0 Found at position 104 (";", ";") 
     1 Found at position 126 (";", ";") 
     2 Found at position 169 (";", ";") 
     3 Found at position 247 (";", ";") 
     4 Found at position 295 (";", ";") 
Pattern "([^;])(\n)" 
     0 Found at position 123 (".\n", ".", "\n") 
     1 Found at position 166 ("e\n", "e", "\n") 
     2 Found at position 242 ("d\n", "d", "\n") 
     3 Found at position 289 ("e\n", "e", "\n") 
     4 Found at position 347 (".\n", ".", "\n") 
Pattern "(?<!;)(\n)" 
     No matches found. 
+0

интересно, не должен быть этот ответ принято. Я полностью согласен с тем, что использование групп захвата лучше, чем использование look-behind/forward, на мой взгляд.Единственная реальная причина, по которой я когда-либо пользуюсь LA/LB, - это когда вы работаете с grep в командной строке, когда мне нужно что-то фильтровать быстро, а иногда и в скриптах с GREP или SED, кроме того, что я его не использую, даже не с Perl, так как в этот момент уже не имеет смысла не использовать захваты. Кроме того, негативный внешний вид сосать все равно, потому что они должны быть фиксированной длины; что раздражает, когда вы точно не знаете, как долго будет строка! – osirisgothra

+0

Мне потребовалось некоторое время, чтобы узнать о неспособности использовать внешний вид переменной длины. Я думал, что сойду с ума. Я, вероятно, должен вернуться к этому ответу и поставить полный тест и решение, показывая, как это должно быть сделано. Вот несколько моих ответов на эту тему: http://stackoverflow.com/search?q=user%3A999943+qregex – phyatt