it-swarm.com.ru

Regex: сопоставить шаблон, если он не в начале

Предположим, следующие строки:

aaa bbb ccc
bbb aaa ccc

Я хочу сопоставить aaa, если это не в начале строки. Я пытаюсь отрицать это, делая что-то вроде этого:

[^^]aaa

Но я не думаю, что это правильно. Использование preg_replace.

19
StackOverflowNewbie

Вы можете использовать взгляд, чтобы убедиться, что это не в начале. (?<!^)aaa

40
Joe

Поскольку я пришел сюда через поиск в Google и заинтересовался решением, которое не использует lookbehind, вот мои 2 цента.

Шаблон [^^]aaa соответствует символу, отличному от ^, а затем 3 as где угодно внутри строки. [^...] - это класс отрицательных символов , где ^ не считается специальным символом. Обратите внимание, что первый ^, который идет сразу после [, является особенным, поскольку он обозначает отрицание, а второй - просто буквальный символ каретки.

Таким образом, ^ не может быть внутри [...] для обозначения начала строки.

Решением является использование любого негативного подхода, эти два будут работать одинаково хорошо:

(?<!^)aaa

и предвкушение:

(?!^)aaa

Почему предвидение работает тоже? Внешний вид - утверждения нулевой ширины, а якоря - также нулевой ширины - они не потребляют текст. В буквальном смысле слова (?<!^) проверяет, нет ли начала строки строки непосредственно слева от текущего местоположения, а (?!^) проверяет, нет ли начала строки строки непосредственно справа от текущего местоположения. Проверяются одинаковые location, поэтому оба работают хорошо.

14
Wiktor Stribiżew

Если вы не хотите использовать lookbehind, используйте это регулярное выражение:

/.(aaa)/

И используйте matched group # 1.

11
anubhava

Эта ситуация - первый раз, когда я вижу, что lookarounds превосходят \K. Интересно.

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

Я добавлю пару \K шаблонов для сравнения.

Я использую модификатор шаблона s на тот случай, если начальный символ может быть символом новой строки (который . обычно не совпадает). Я просто подумал, что добавлю это соображение, чтобы превентивно рассмотреть крайнее дело, которое я могу поставить.

Опять же, это интересный сценарий, потому что во всех других случаях регулярных выражений, с которыми я имел дело, \K превосходит другие методы.

Таблица сравнения количества шагов:

              | `~.\Kaaa~s` | `~.+?\Kaaa~s` | `(?<!^)aaa` | `(?!^)aaa` | `.(aaa)` |
--------------|-------------|---------------|-------------|------------|----------|
`aaa bbb ccc` |   12 steps  |    67 steps   |   8 steps   |  8 steps   | 16 steps |
--------------|-------------|---------------|-------------|------------|----------|
`bbb aaa ccc` |   15 steps  |    12 steps   |   6 steps   |  6 steps   | 12 steps |

Вывод: чтобы узнать об эффективности ваших шаблонов, разбейте их на regex101.com и сравните количество шагов.

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

2
mickmackusa

Я пришел сюда, чтобы найти решение для движка re2, используемого в электронных таблицах Google, который не поддерживает обходные пути . Но ответы на этот вопрос дали мне идею использования следующего .. Я не понимаю, почему я нужно заменить захваченной группой, но в любом случае, это работает.

ааа bbb ccc
BBB AAA CCC

([^^])aaa

заменить на:

$1zzz

переходит в:

ааа bbb ccc
bbb zzz ccc

0
Timar Ivo Batis

Это поможет найти то, что вы ищете:

(?<!^)aaa

Пример использования: http://regexr.com?34ab2

0
Daedalus