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

515

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

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

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

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

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

Каллум
источник
Что вы имеете в виду match but not including?
Тото
5
Я имею в виду, я хочу соответствовать "qwerty qwerty whatever "- не считая "abc". Другими словами, я не хочу, чтобы полученное совпадение было "qwerty qwerty whatever abc".
Каллум
2
В javascript вы можете просто do string.split('abc')[0]. Конечно, не официальный ответ на эту проблему, но я нахожу это более простым, чем регулярное выражение.
Уильям Джадд

Ответы:

1023

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

/.+?(?=abc)/

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

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

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

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

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

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

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

Подбирайте как можно меньше символов, пока не найдете «abc», не считая «abc».

sidyll
источник
12
Это, вероятно, не будет работать с переносами строк, если они должны быть захвачены.
Einord
3
Какая разница между .+?а .*?
Robbie
4
@ robbie0630 +означает 1 или более, где *означает 0 или более. Включение / исключение ?сделает его жадным или не жадным.
jinglesthula
2
@ testerjoe2 /.+?(?=abc|xyz)/
JohnWrensby
4
Я заметил, что ничего не выбирается, если шаблон, который вы ищете, не существует, вместо этого, если вы используете ^(?:(?!abc)(?!def).)*цепочку, вы можете исключить шаблоны, которые вам не нужны, и он все равно будет захватывать все по мере необходимости, даже если шаблон не существует
Каран Шишу
123

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

/^(.*?)abc/

Объяснение:

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

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

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

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

whatever whatever something abc something abc

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

Джаред Нг
источник
4
Спасибо, но ваш один делает включать Азбуки в матче. Другими словами, полученное совпадение - «что угодно, что-то, abc».
Каллум
1
Не могли бы вы объяснить, что вы в конечном итоге пытаетесь сделать? Если ваш сценарий: (A) Вы хотите получить все, что приводит к «abc» - просто используйте скобки вокруг того, что вы хотите захватить. (B) Вы хотите сопоставить строку с «abc» - вы все равно должны проверить abc, поэтому она должна быть частью регулярного выражения независимо от этого. Как еще можно проверить, что это там?
Джаред Нг
sedкажется, не поддерживает не жадное сопоставление, и при этом не поддерживает осмотр ( (?=...)). Что еще я могу сделать? Пример команды: echo "ONE: two,three, FOUR FIVE, six,seven" | sed -n -r "s/^ONE: (.+?), .*/\1/p"возвращает two,three, FOUR FIVE, но я ожидаю two,three...
CodeManX
1
@CoDEmanX Вы, вероятно, должны опубликовать это как отдельный вопрос, а не как комментарий, тем более что речь идет именно о sed. При этом, чтобы ответить на ваш вопрос: вы можете посмотреть на ответы на этот вопрос . Также обратите внимание, что в вашем примере не жадный осведомленный интерпретатор вернул бы просто two, а не two,three.
Джаред Нг
3
Так должен выглядеть КАЖДЫЙ ответ регулярного выражения - пример и объяснение всех частей ...
jave.web
54

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

В вашем конкретном случае это может быть решено положительным взглядом в будущее: .+?(?=abc)

Одна картинка стоит тысячи слов. Смотрите подробное объяснение на скриншоте.

Скриншот Regex101

Devy
источник
23
.+?(?=abc)копируемое регулярное выражение стоит больше.
Том
Как насчет исключения пробелов?
Рой
8

То, что вам нужно, это посмотреть на утверждение как .+? (?=abc).

См .: Взгляд вперед и взгляд назад.

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

aevanko
источник
7

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

.+?(abc)

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

I have this very nice senabctence

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

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

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

Dadan
источник
4

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

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

введите описание изображения здесь

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

редактировать

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

.*\/grp-bps\/[^\/]+
Loaderon
источник
6
Нет текстовой версии? K
kiradotee
2

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

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

("(.*?)")/г

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

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

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

Понмуруган Моханрадж
источник
Добро пожаловать в StackOverflow и спасибо за вашу попытку помочь. Однако мне трудно понять, как это помогает цели, изложенной в вопросе. Можете ли вы уточнить? Можете ли вы применить его к приведенным примерам? Вы, кажется, сосредоточены на обработке ", что мне кажется несущественным для вопроса.
Yunnosch
1
Привет, я объяснил, как получить слово или предложения между специальными символами. Здесь наш вопрос также «что-нибудь, пока последовательность специальных символов». поэтому я попытался с двойными кавычками и объяснил это здесь. Спасибо.
Понмуруган Моханрай
2

На питоне:

.+?(?=abc) работает для однострочного случая.

[^]+?(?=abc)не работает, так как python не распознает [^] как правильное регулярное выражение. Чтобы обеспечить многострочное сопоставление, вам нужно использовать параметр re.DOTALL, например:

re.findall('.+?(?=abc)', data, re.DOTALL)
Дэвид Малдер
источник
0

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

Эта часть из руководства 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)]должно сделать свое дело.

Нандини Ананд
источник
Извините, это не работает. Помещение букв в скобках, похоже, не имеет никакого значения. Они по-прежнему рассматриваются как «ИЛИ b ИЛИ c».
Каллум
-1

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

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

Джекоб
источник
-6

попробуй это

.+?efg

Запрос:

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

вывод :

hijklmn
Балакришна Гондези
источник