Как совместить "все до этой последовательности символов" в регулярном выражении?

Возьмем это регулярное выражение: /^[^abc]/. Это будет соответствовать любому одиночному символу в начале строки, кроме a, b или c.

Если вы добавите * после него - /^[^abc]*/ - регулярное выражение будет продолжать добавлять каждый последующий символ к результату, пока не встретит либо a, или b, или c.

Например, с исходной строкой "qwerty qwerty whatever abc hello" выражение будет соответствовать "qwerty qwerty wh".

Но что, если я хочу, чтобы строка соответствия была "qwerty qwerty whatever "

... Другими словами, как я могу сопоставить все до (но не включая) точную последовательность "abc"?

Ответ 1

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

/.+?(?=abc)/

Как это работает

Часть .+? - это нежелательная версия .+ (одна или несколько что-нибудь). Когда мы используем .+, двигатель будет в основном соответствовать всем. Затем, если в регулярном выражении есть что-то еще, он вернется по шагам пытаясь соответствовать следующей части. Это поведение жадного, что означает как можно больше, чтобы удовлетворить.

При использовании .+? вместо одновременного совпадения и возврата другие условия (если они есть), двигатель будет соответствовать следующим символам шаг, пока последующая часть регулярного выражения не будет сопоставлена ​​(опять же, если таковая имеется). Это un-greedy, что означает соответствие максимально возможного удовлетворяют условию.

/.+X/  ~ "abcXabcXabcX"        /.+/  ~ "abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~ "abcXabcXabcX"        /.+?/ ~ "abcXabcXabcX"
          ^^^^                          ^

После этого мы имеем (?= {contents} ), нулевую ширину утверждение, взгляд вокруг. Эта сгруппированная конструкция соответствует содержимое, но не считается совпадающим символом (нулевая ширина). Это возвращается только в случае совпадения (утверждение).

Таким образом, другими словами, регулярное выражение /.+?(?=abc)/ означает:

Сопоставьте любые символы как можно меньше, пока не будет найдено "abc", без учета "abc".

Ответ 2

Если вы хотите захватить все до "abc":

/^(.*?)abc/

Пояснение:

( ) захватить выражение внутри круглых скобок для доступа с помощью $1, $2 и т.д.

^ соответствует началу строки

.* соответствовать чему-либо, ? не жадному (соответствует минимальному количеству символов) - [1]

[1] Причина, по которой это необходимо, заключается в том, что в противном случае в следующей строке:

whatever whatever something abc something abc

по умолчанию, регулярные выражения являются жадными, то есть они будут соответствовать как можно больше. Поэтому /^.*abc/ будет соответствовать "независимо от чего-то что-то". Добавление не-жадного квантификатора ? делает регулярное выражение только "независимо от чего-то".

Ответ 3

Как отметили @Jared Ng и @Issun, ключ для решения такого рода регулярных выражений, как "сопоставление всего до определенного слова или подстроки" или "сопоставление всего после определенного слова или подстроки", называется "косвенным" утверждением нулевой длины, Подробнее о них читайте здесь.

В вашем конкретном случае это можно решить путем позитивного взгляда в будущее. Одна картинка стоит тысячи слов. Смотрите подробное объяснение на скриншоте.

Regex101 Screenshot

Ответ 4

Что вам нужно, посмотрите вокруг утверждения вроде .+? (?=abc).

Смотрите: Утверждения с нулевой длиной Lookahead и Lookbehind

Помните, что [abc] не совпадает с abc. Внутри скобок это не строка - каждый символ является лишь одной из возможностей. За пределами скобок она становится строкой.

Ответ 5

Для regex в Java, и я верю также в большинство движков регулярных выражений, если вы хотите включить последнюю часть, это будет работать:

.+?(abc)

Например, в этой строке:

I have this very nice senabctence

выберите все символы до "abc", а также включите abc

используя наше регулярное выражение, результат будет: I have this very nice senabc

Проверьте это: https://regex101.com/r/mX51ru/1

Ответ 6

Это будет иметь смысл в отношении регулярного выражения.

  • Точное слово можно получить из следующей команды regex:

( "(. *?)" )/Г

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

Это пример слов с двойными кавычками

то мы получим "двойное кавычку" из этого предложения.

Ответ 7

Я остановился на этом вопросе stackoverflow после поиска помощи для решения моей проблемы, но не нашел ее решения :(

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

enter image description here

Как видите, мне нужно было до одной папки впереди папки "grp-bps", без учета последней черты. И нужно было иметь хотя бы одну папку после папки "grp-bps".

Изменить

Текстовая версия для копирования-вставки (измените "grp-bps" для своего текста):

. */GRP-бит/[^/] +

Ответ 8

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

Эта часть из руководства grep:

 Back References and Subexpressions
       The back-reference \n, where n is a single digit, matches the substring
       previously matched  by  the  nth  parenthesized  subexpression  of  the
       regular expression.

Сделайте что-то вроде ^[^(abc)], чтобы сделать трюк.

Ответ 9

$ обозначает конец строки, поэтому что-то вроде этого должно работать: [[^abc]*]$, где вы ищете что-то НЕ ЗАВЕРШЕНО в любой итерации abc, но это должно быть в конце

Также, если вы используете язык сценариев с регулярным выражением (например, php или js), у них есть функция поиска, которая останавливается, когда она впервые встречает шаблон (и вы можете указать начало слева или начинать с правой стороны, или с php, вы можете сделать imode для зеркалирования строки).

Ответ 10

попробуйте это

.+?efg

Запрос:

select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;

вывод:

hijklmn