Я хотел бы упомянуть возможный ход действий при столкновении с ситуацией, например, здесь, где требуется положительный просмотр переменной длины, но используемый механизм регулярных выражений не поддерживает эту операцию, но поддерживает положительные взгляды переменной длины. Как и PCRE (PHP), например.
Признаюсь, что в основном я написал этот ответ, чтобы улучшить мое собственное понимание работы двигателей регулярных выражений.
Basi c idea
- Перевернуть строку
- Использовать регулярное выражение с соответствующим положительным прогнозом для замены совпадений
- Перевернуть результирующую строку
Пример
Предположим, мы wi sh преобразуем следующие строки:
a, bb, c, d
ee, f, g, h
i, j, kk, l
в строки:
abb, ac, ad
eef, eeg, eeh
ij, ikk, il
Сначала мы переворачиваем исходные строки:
d ,c ,bb ,a
h ,g ,f ,ee
l ,kk ,j ,i
, затем сопоставляем регулярное выражение:
(\w+)(?=.*,(\w+)$)|\s+,\w+$
и заменяем каждое совпадение на $1+$2
, чтобы получить:
da ,ca ,bba
hee ,gee ,fee
li ,kki ,ji
Наконец, переверните эти строки:
abb, ac, ad
eef, eeg, eeh
ij, ikk, il
PCRE demo
Регулярное выражение выполняет следующие операции:
(\w+) # match 1+ word chars in cap grp 1
(?= # begin a positive lookahead
.*, # match 0+ chars (greedily), then ','
(\w+) # match 1+ word chars in cap grp 1
$
)
|
\s+,\w+
$
Я буду представлять пробелы в строке "a, bb, c, d"
с небольшими смайликами (☺
), чтобы сделать их более четкими и отобразить строку таким образом:
a , ☺ b b , ☺ c , ☺ d
^
Пробелы теперь представляют области между соседними символами. ^
- начальное расположение указателя движка регулярных выражений.
После того, как (\w+)
соответствует "a"
в начале строки (обозначено m
ниже), "a"
сохраняется в группу захвата. 1. Позитивный прогноз начинается сразу после этого матча:
a , ☺ b b , ☺ c , ☺ d
m^
Позитивный прогноз (?=.*,(\w+)$)
сохраняет "d"
, чтобы захватить группу 2. 1 Поскольку матч был успешным, При первом совпадении "a"
заменяется на $1+$2 #=> "ad"
, и указатель перемещается обратно на свою позицию до того, как был выполнен поиск:
a , ☺ b b , ☺ c , ☺ d
^
Теперь есть попытка сопоставить (\w+)
с частью строка, которая начинается с первой запятой. Это терпит неудачу, как и или часть регулярного выражения, \s+,\w+$
. Затем указатель передвигается на один символ:
a , ☺ b b , ☺ c , ☺ d
^
Это также не удается, и указатель снова передвигается на единицу.
a , ☺ b b , ☺ c , ☺ d
^
(\w+)
теперь соответствует "bb"
, что сохраняется для захвата группы 1, и в этот момент:
a , ☺ b b , ☺ c , ☺ d
m m^
Как и прежде, положительный прогноз сохраняет "d"
для захвата группы 2 и совпадения, "bb"
заменяется на $1+$2 #=> "bbd"
После еще двух совпадающих сбоев мы находимся по адресу:
a , ☺ b b , ☺ c , ☺ d
^
По тем же причинам, что и раньше, "c"
сопоставляется и заменяется на $1+$2 => "cd"
, и мы сейчас здесь:
a , ☺ b b , ☺ c , ☺ d
^
Больше нет строк слов, за которыми следуют строки слов, которые должны быть сопоставлены, но конец строки, ", d"
, теперь соответствует части или регулярного выражения \s+,\w+$
. Это совпадение затем заменяется на $1+$2
. Однако на этот раз две группы захвата пусты, поэтому совпадение заменяется пустой строкой.
1 Необходима запятая. Без этого .*
, будучи жадным, сожрал бы все до последнего символа слова. Например, если строка заканчивается ", cd"
, группа захвата 2 будет содержать только "d"
.