Лексемы в регулярных выражениях

Введение

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

Каждой лексеме в выражении присваивают номер, запускающийся от 1, идя слева направо. Чтобы сделать ссылку на лексему позже в выражении, обратитесь к нему с помощью обратной косой черты, сопровождаемой маркерным номером. Например, при ссылке на лексему, сгенерированную третьим набором круглых скобок в выражении, используйте \3.

Как простой пример, если вы хотели искать идентичные последовательные буквы в символьном массиве, вы могли бы получить первую букву как лексему и затем искать соответствующий символ сразу впоследствии. В выражении, показанном ниже, (\S) фраза создает лексему каждый раз, когда regexp соответствия любой непробельный символ в символьном массиве. Вторая часть выражения, '\1', ищет второй экземпляр того же символа сразу после первого.

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

[mat,tok,ext] = regexp(poe, '(\S)\1', 'match', ...
               'tokens', 'tokenExtents');
mat
mat =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

Массив ячеек tok содержит массивы ячеек, что каждый содержит лексему.

tok{:}
ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}


ans =

  1×1 cell array

    {'d'}


ans =

  1×1 cell array

    {'p'}

Массив ячеек ext содержит числовые массивы, что каждый содержит начальные и конечные индексы для лексемы.

ext{:}
ans =

    11    11


ans =

    26    26


ans =

    35    35


ans =

    57    57

Для другого примера получите пары соответствия с HTML-тэгами (например, <a> и </a>) и текст между ними. Выражение, используемое для этого примера,

expr = '<(\w+).*?>.*?</\1>';

Первая часть выражения, '<(\w+)', совпадает с открывающей угловой скобкой (<) сопровождаемый одним или несколькими алфавитные, числовые, или символы подчеркивания. Круглые скобки включения получают маркерные символы после открывающей угловой скобки.

Вторая часть выражения, '.*?>.*?', совпадает с остатком от этого HTML-тэга (символы до >), и любые символы, которые могут предшествовать следующей открывающей угловой скобке.

Последняя часть, '</\1>', соответствия все символы в конечном HTML-тэге. Этот тег состоит из последовательности </tag>, где tag любые символы, были получены как лексема.

hstr = '<!comment><a name="752507"></a><b>Default</b><br>';
expr = '<(\w+).*?>.*?</\1>';

[mat,tok] = regexp(hstr, expr, 'match', 'tokens');
mat{:}
ans =

    '<a name="752507"></a>'


ans =

    '<b>Default</b>'
tok{:}
ans =

  1×1 cell array

    {'a'}


ans =

  1×1 cell array

    {'b'}

Несколько лексем

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

andy ted bob jim andrew andy ted mark

Вы принимаете решение искать вышеупомянутый текст со следующим поисковым шаблоном:

and(y|rew)|(t)e(d)

Этот шаблон имеет три вводных выражения, которые генерируют лексемы. Когда вы наконец выполняете поиск, следующие лексемы сгенерированы для каждого соответствия.

Соответствие

Лексема 1

Лексема 2

andy

y

 

ted

t

d

andrew

rew

 

andy

y

 

ted

t

d

Только круглые скобки высшего уровня используются. Например, если поисковый шаблон and(y|rew) находит текст andrew, лексема 1 присвоена значение rew. Однако, если поисковый шаблон (and(y|rew)) используется, лексема 1 присвоена значение andrew.

Несопоставленные лексемы

Для тех лексем, заданных в регулярном выражении, которые не имеют никакого соответствия в оцениваемом тексте, regexp и regexpi возвратите пустой символьный вектор ('') как маркерный выход и степень, которая отмечает положение в строке, где лексема ожидалась.

Пример, показанный здесь, выполняет regexp на векторе символов, задающем путь, возвращенный в MATLAB® tempdir функция. Регулярное выражение expr включает шесть маркерных спецификаторов, один для каждой части пути. Третий спецификатор [a-z]+ не имеет никакого соответствия в векторе символов потому что эта часть пути, Profiles, начинается с прописной буквы:

chr = tempdir
chr =

    'C:\WINNT\Profiles\bpascal\LOCALS~1\Temp\'
expr = ['([A-Z]:)\\(WINNT)\\([a-z]+)?.*\\' ...
        '([a-z]+)\\([A-Z]+~\d)\\(Temp)\\'];

[tok, ext] = regexp(chr, expr, 'tokens', 'tokenExtents');

Когда лексема не найдена в тексте, regexp возвращает пустой символьный вектор ('') как лексема и числовой массив с маркерной степенью. Первое количество степени является индексом строк, который отмечает, где лексема ожидалась, и второе количество степени равно меньше, чем первое.

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

tok{:}
ans =

  1×6 cell array

    {'C:'}    {'WINNT'}    {0×0 char}    {'bpascal'}    {'LOCALS~1'}    {'Temp'}

Третья маркерная степень возвращена в переменной ext установили начальное значение индекса на 10, который является где не соответствующий термин, Profiles, начинается в пути. Конечный индекс степени установлен в меньше, чем начальное значение индекса, или 9:

ext{:}
ans =

     1     2
     4     8
    10     9
    19    25
    27    34
    36    39

Лексемы в Замещаемом тексте

При использовании лексем в тексте замены сошлитесь на них использующий $1, $2, и т.д. вместо \1, \2, и т.д. Этот пример получает две лексемы и инвертирует их порядок. Первое, $1, 'Norma Jean' и второе, $2, 'Baker'. Обратите внимание на то, что regexprep возвращает модифицированный текст, не вектор из начальных значений индекса.

regexprep('Norma Jean Baker', '(\w+\s\w+)\s(\w+)', '$2, $1')
ans =

    'Baker, Norma Jean'

Названное получение

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

При ссылке на именованную лексему в рамках выражения используйте синтаксис \k<name> вместо числового \1, \2, и т.д.:

poe = ['While I nodded, nearly napping, ' ...
       'suddenly there came a tapping,'];

regexp(poe, '(?<anychar>.)\k<anychar>', 'match')
ans =

  1×4 cell array

    {'dd'}    {'pp'}    {'dd'}    {'pp'}

Названные лексемы могут также быть полезными в маркировке выхода от функций регулярного выражения MATLAB. Это особенно верно, когда вы обрабатываете много частей текста.

Например, проанализируйте различные части конкретных адресов от нескольких векторов символов. Краткое название присвоено каждой лексеме в выражении:

chr1 = '134 Main Street, Boulder, CO, 14923';
chr2 = '26 Walnut Road, Topeka, KA, 25384';
chr3 = '847 Industrial Drive, Elizabeth, NJ, 73548';

p1 = '(?<adrs>\d+\s\S+\s(Road|Street|Avenue|Drive))';
p2 = '(?<city>[A-Z][a-z]+)';
p3 = '(?<state>[A-Z]{2})';
p4 = '(?<zip>\d{5})';

expr = [p1 ', ' p2 ', ' p3 ', ' p4];

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

loc1 = regexp(chr1, expr, 'names')
loc1 = 

  struct with fields:

     adrs: '134 Main Street'
     city: 'Boulder'
    state: 'CO'
      zip: '14923'
loc2 = regexp(chr2, expr, 'names')
loc2 = 

  struct with fields:

     adrs: '26 Walnut Road'
     city: 'Topeka'
    state: 'KA'
      zip: '25384'
loc3 = regexp(chr3, expr, 'names')
loc3 = 

  struct with fields:

     adrs: '847 Industrial Drive'
     city: 'Elizabeth'
    state: 'NJ'
      zip: '73548'

Смотрите также

| |

Похожие темы