Python Regex: игнорировать побег персонажа - PullRequest
3 голосов
/ 08 декабря 2011

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

'key1:"this is a test phrase"; key2:"this is another test phrase"; key3:"ok this is a gotcha\; but you should get it";'

Регулярное выражение: \s*([^;]+[^\\])\s*;

В настоящее время я использую описанный выше pcre, который работал нормально, пока я не столкнулся со случаем, когда экранированная точка с запятой включена в одну из фраз, как отмечено выше key3.

Как изменить это выражение, чтобы оно разделялось только на неэкранированные точки с запятой?

Ответы [ 2 ]

1 голос
/ 08 декабря 2011

Если строка может содержать точки с запятой и экранированные кавычки (или экранировать что-нибудь ), я бы предложил проанализировать каждую действительную последовательность key:"value"; Вот так:

import re
s = r'''
    key1:"this is a test phrase";
    key2:"this is another test phrase";
    key3:"ok this is a gotcha\; but you should get it";
    key4:"String with \" escaped quote";
    key5:"String with ; unescaped semi-colon";
    key6:"String with \\; escaped-escape before semi-colon";
    '''
result = re.findall(r'\w+:"[^"\\]*(?:\\.[^"\\]*)*";', s)
print (result)

Обратите внимание, что это правильно обрабатывает любые escape-символы в строке в двойных кавычках.

1 голос
/ 08 декабря 2011

В базовой версии вы хотите игнорировать любой ;, которому предшествует обратный слеш, независимо от чего-либо еще.Это относительно просто:

\s*([^;]*[^;\\]);

Что будет сложно, если вы хотите, чтобы экранированные обратные слэши во входных данных рассматривались как литералы.Например:

"You may want to split here\\;"
"But not here\;"

Если вы хотите принять это во внимание, попробуйте это (отредактировано) :

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

Почему так сложно?Потому что, если разрешены экранированные обратные слэши, вы должны учитывать такие вещи:

"0 slashes; 2 slashes\\; 5 slashes\\\\\; 6 slashes\\\\\\;"

Каждая пара удвоенных обратных слэшей будет рассматриваться как литерал \.Это означает, что ; будет экранирован только в том случае, если перед ним будет нечетное число обратной косой черты.Таким образом, вышеприведенный ввод будет сгруппирован следующим образом:

#1: '0 slashes'
#2: '2 slashes\'
#3: '5 slashes\\; 6 slashes\\\'

Отсюда и различные части шаблона:

\s*            #Whitespace
((?:
    [^;\\]     #One character that's not ; or \
  |            #Or...
    \\.        #A backslash followed by any character, even ; or another backslash
)+);           #Repeated one or more times, followed by ;

Требование символа после обратной косой черты гарантирует, что второй символ всегда будет экранированправильно, даже если это еще один обратный слеш.

...