Динамические регулярные выражения

Введение

В динамическом выражении можно сделать шаблон, с которым вы хотите, чтобы regexp совпадал зависящий от содержимого входного текста. Таким образом можно более тесно совпадать с переменными входными наборами в проанализированном тексте. Можно также использовать динамические выражения в заменяющих условиях для использования с функцией regexprep. Это дает вам способность адаптировать текст замены к проанализированному входному параметру.

Можно включать любое количество динамических выражений в аргументах match_expr или replace_expr этих команд:

regexp(text, match_expr)
regexpi(text, match_expr)
regexprep(text, match_expr, replace_expr)

Как пример динамического выражения, следующая команда regexprep правильно заменяет термин internationalization на его сокращенную форму, i18n. Однако, чтобы использовать его на различном термине, таком как globalization, необходимо использовать различное выражение замены:

match_expr = '(^\w)(\w*)(\w$)';

replace_expr1 = '$118$3';
regexprep('internationalization', match_expr, replace_expr1)
ans =
    i18n
replace_expr2 = '$111$3';
regexprep('globalization', match_expr, replace_expr2)
ans =
    g11n

Используя динамическое выражение ${num2str(length($2))} позволяет вам основывать выражение замены на входном тексте так, чтобы вы не изменяли выражение каждый раз. Этот пример использует динамический заменяющий синтаксис ${cmd}.

match_expr = '(^\w)(\w*)(\w$)';
replace_expr = '$1${num2str(length($2))}$3';

regexprep('internationalization', match_expr, replace_expr)
ans =
    i18n
regexprep('globalization', match_expr, replace_expr)
ans =
    g11n

Когда проанализировано, динамическое выражение должно соответствовать полному, действительному регулярному выражению. Кроме того, динамические выражения соответствия, которые используют символ ESC наклонной черты влево (\), требуют двух наклонных черт влево: один для начального парсинга выражения, и один для полного соответствия. Круглые скобки, которые заключают динамические выражения, не создают группу фиксации.

Существует три формы динамических выражений, которые можно использовать в выражениях соответствия и одной форме для выражений замены, как описано в следующих разделах

Динамические выражения соответствия - (?? expr)

Оператор (??expr) анализирует выражение expr и вставляет результаты назад в выражение соответствия. MATLAB® затем оценивает измененное выражение соответствия.

Вот пример типа выражения, которое можно использовать с этим оператором:

chr = {'5XXXXX', '8XXXXXXXX', '1X'};
regexp(chr, '^(\d+)(??X{$1})$', 'match', 'once');

Цель этой конкретной команды состоит в том, чтобы определить местоположение серии символов X в каждых из векторов символов, сохраненных во входном массиве ячеек. Обратите внимание, однако, что количество X s отличается по каждому вектору символа. Если бы количество не отличалось, вы могли бы использовать выражение X{n}, чтобы указать, что вы хотите совпадать с n этих символов. Но, постоянное значение n не работает в этом случае.

Решение, используемое здесь, состоит в том, чтобы получить ведущий номер количества (e. g., 5 в первом векторе символа массива ячеек) в лексеме, и затем использовать то количество в динамическом выражении. Динамическим выражением в этом примере является (??X{$1}), где $1 является значением, полученным маркерным \d+. Оператор {$1} делает квантор той символической стоимости. Поскольку выражение является динамическим, тот же шаблон работает на всех трех из входных векторов в массиве ячеек. С первым вектором вводимого символа regexp ищет пять символов X; со вторым это ищет восемь, и с третьим, это ищет всего один:

regexp(chr, '^(\d+)(??X{$1})$', 'match', 'once')
ans = 
    '5XXXXX'    '8XXXXXXXX'    '1X'

Команды, которые изменяют выражение соответствия - (??@cmd)

MATLAB использует оператор (??@cmd), чтобы включать результаты команды MATLAB в выражении соответствия. Эта команда должна возвратить термин, который может быть использован в рамках выражения соответствия.

Например, используйте динамическое выражение (??@flilplr($1)), чтобы определить местоположение палиндрома, “Никогда Нечетный или Даже”, который был встроен в больший вектор символа.

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

chr = lower(...
  'Find the palindrome Never Odd or Even in this string');

chr = regexprep(str, '\W*', '')
chr =
   findthepalindromeneveroddoreveninthisstring

Найдите палиндром в векторе символа с помощью динамического выражения:

palchr = regexp(chr, '(.{3,}).?(??@fliplr($1))', 'match')
palchr =
   'neveroddoreven'

Динамическое выражение инвертирует порядок букв, которые составляют вектор символа, и затем пытается совпадать с как можно большим количеством вектора обратного порядка. Это требует динамического выражения, потому что значение для $1 полагается на значение маркерного (.{3,}).

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

fun = @fliplr;

palchr = regexp(str, '(.{3,}).?(??@fun($1))', 'match')
palchr =
   'neveroddoreven'

Команды, которые служат функциональной цели - (?@cmd)

Оператор (?@cmd) задает команду MATLAB, которую regexp или regexprep должны запустить при парсинге полного выражения соответствия. В отличие от других динамических выражений в MATLAB, этот оператор не изменяет содержимое выражения, в котором это используется. Вместо этого можно использовать эту функциональность, чтобы заставить MATLAB сообщать, что продвигается, это берет, когда это анализирует содержимое одного из регулярных выражений. Эта функциональность может быть полезной в диагностировании ваших регулярных выражений.

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

regexp('mississippi', '\w*(\w)\1\w*', 'match')
ans = 
    'mississippi'

Отслеживать точные шаги, что взятия MATLAB в определении соответствия, пример вставляет короткий скрипт (?@disp($1)) в выражение, чтобы отобразить символы, которые наконец составляют соответствие. Поскольку пример использует жадные кванторы, MATLAB пытается совпадать с как можно большим количеством вектора символа. Так, даже при том, что MATLAB находит соответствие к началу строки, это продолжает искать больше соответствий, пока это не прибывает в самый конец строки. Оттуда, это поддерживает через буквы i затем p и следующий p, останавливающийся в той точке, потому что соответствие наконец удовлетворено:

regexp('mississippi', '\w*(\w)(?@disp($1))\1\w*', 'match')
i
p
p

ans = 
    'mississippi'

Теперь попробуйте тот же пример снова, на этот раз делая первый квантор ленивым (*?). Снова, MATLAB делает то же соответствие:

regexp('mississippi', '\w*?(\w)\1\w*', 'match')
ans = 
    'mississippi'

Но путем вставки динамического скрипта, вы видите, что на этот раз, MATLAB совпадал с текстом вполне по-другому. В этом случае MATLAB использует самое первое соответствие, которое он может найти и даже не рассматривает остальную часть текста:

regexp('mississippi', '\w*?(\w)(?@disp($1))\1\w*', 'match')
m
i
s

ans = 
    'mississippi'

Чтобы продемонстрировать, насколько универсальный этот тип динамического выражения может быть, рассмотрите следующий пример, который прогрессивно собирает массив ячеек, когда MATLAB многократно анализирует входной текст. Оператор (?!), найденный в конце выражения, является на самом деле пустым предварительным оператором и обеспечивает отказ в каждой итерации. Этот принудительный отказ необходим, если вы хотите проследить шаги, которые MATLAB делает, чтобы разрешить выражение.

MATLAB делает, много проходят через входной текст, каждый раз пробуя другую комбинацию букв, чтобы видеть, может ли соответствие лучше, чем последнее соответствие быть найдено. На любых передачах, в которых никакие соответствия не найдены, результаты испытаний в пустом символьном векторе. Динамический скрипт (?@if(~isempty($&))) служит, чтобы не использовать пустые символьные вектора от массива ячеек matches:

matches = {};
expr = ['(Euler\s)?(Cauchy\s)?(Boole)?(?@if(~isempty($&)),' ...
   'matches{end+1}=$&;end)(?!)'];

regexp('Euler Cauchy Boole', expr);

matches
matches = 
    'Euler Cauchy Boole'    'Euler Cauchy '    'Euler '    
'Cauchy Boole'    'Cauchy '    'Boole'

$& операторов (или эквивалентный $0), $` и $' относится к той части входного текста, который в настоящее время является соответствием, все символы, которые предшествуют текущему соответствию и всем символам, чтобы следовать за текущим соответствием, соответственно. Эти операторы иногда полезны при работе с динамическими выражениями, особенно те, которые используют оператор (?@cmd).

Этот пример анализирует входной текст, ища букву g. В каждой итерации через текст regexp сравнивает текущий символ с g, и не нахождение его, усовершенствования к следующему символу. Пример отслеживает прогресс сканирования через текст путем маркировки текущего местоположения, проанализированного с символом ^.

($` и операторы получают ту часть текста, который предшествует и следует за текущим местоположением парсинга. Вам нужны два одинарных кавычек ($''), чтобы выразить последовательность , когда это появляется в рамках текста.)

chr = 'abcdefghij';
expr = '(?@disp(sprintf(''starting match: [%s^%s]'',$`,$'')))g';

regexp(chr, expr, 'once');
starting match: [^abcdefghij]
starting match: [a^bcdefghij]
starting match: [ab^cdefghij]
starting match: [abc^defghij]
starting match: [abcd^efghij]
starting match: [abcde^fghij]
starting match: [abcdef^ghij]

Команды в выражениях замены — $ {cmd}

Оператор ${cmd} изменяет содержимое заменяющего шаблона регулярного выражения, делая этот шаблон адаптируемым к параметрам во входном тексте, который может отличаться от одного использования до следующего. Как с другими динамическими выражениями, используемыми в MATLAB, можно включать любое количество этих выражений в полном выражении замены.

В вызове regexprep, показанном здесь, заменяющим шаблоном является '${convertMe($1,$2)}'. В этом случае целый заменяющий шаблон является динамическим выражением:

regexprep('This highway is 125 miles long', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}');

Динамическое выражение говорит MATLAB выполнять функцию с именем convertMe с помощью этих двух лексем (\d+\.?\d*) и (\w+), выведенный из соответствующего текста, как входные параметры в вызове convertMe. Заменяющий шаблон требует динамического выражения, потому что значения $1 и $2 сгенерированы во времени выполнения.

Следующий пример задает файл с именем convertMe, который преобразовывает измерения от имперских модулей до метрики.

function valout  = convertMe(valin, units)
switch(units)
    case 'inches'
        fun = @(in)in .* 2.54;
        uout = 'centimeters';
    case 'miles'
        fun = @(mi)mi .* 1.6093;
        uout = 'kilometers';
    case 'pounds'
        fun = @(lb)lb .* 0.4536;
        uout = 'kilograms';
    case 'pints'
        fun = @(pt)pt .* 0.4731;
        uout = 'litres';
    case 'ounces'
        fun = @(oz)oz .* 28.35;
        uout = 'grams';
end
val = fun(str2num(valin));
valout = [num2str(val) ' ' uout];
end

В командной строке вызовите функцию convertMe от regexprep, передающего в значениях для количества, которое будет преобразовано и имя имперского модуля:

regexprep('This highway is 125 miles long', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}')
ans =
   This highway is 201.1625 kilometers long
regexprep('This pitcher holds 2.5 pints of water', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}')
ans =
   This pitcher holds 1.1828 litres of water
regexprep('This stone weighs about 10 pounds', ...
          '(\d+\.?\d*)\W(\w+)', '${convertMe($1,$2)}')
ans =
   This stone weighs about 4.536 kilograms

Как с оператором (??@ ), обсужденным в более раннем разделе, оператор ${ } имеет доступ к переменным в в настоящее время активной рабочей области. Следующая команда regexprep использует массив A, заданный в базовом рабочем пространстве:

A = magic(3)
A =
     8     1     6
     3     5     7
     4     9     2
regexprep('The columns of matrix _nam are _val', ...
          {'_nam', '_val'}, ...
          {'A', '${sprintf(''%d%d%d '', A)}'})
ans =
The columns of matrix A are 834 159 672

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

| |

Похожие темы

Была ли эта тема полезной?