Як зіставити "що-небудь до цієї послідовності символів" у регулярному виразі?


514

Візьміть це регулярний вираз: /^[^abc]/. Це буде відповідати будь-якому одному символу на початку рядка, за винятком a, b або c.

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

Наприклад, з вихідним рядком "qwerty qwerty whatever abc hello"вираз буде відповідати до "qwerty qwerty wh".

Але що робити, якщо я хотів, щоб ця відповідна рядок була "qwerty qwerty whatever "

... Іншими словами, як я можу зіставити все до (але не включаючи) точної послідовності "abc" ?


Що ви маєте на увазі під match but not including?
Toto

5
Я маю на увазі, що я хочу відповідати "qwerty qwerty whatever "- не включаючи "abc". Іншими словами, я не хочу, щоб результатом цього матчу було "qwerty qwerty whatever abc".
callum

2
У JavaScript ви можете просто do string.split('abc')[0]. Звичайно, це не офіційна відповідь на цю проблему, але я вважаю це більш прямим, ніж регулярний вираз.
Вілліям Джадд

Відповіді:


1020

Ви не вказали, який аромат регексу ви використовуєте, але це буде працювати в будь-якому з найпопулярніших, який можна вважати "завершеним".

/.+?(?=abc)/

Як це працює

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

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

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

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

Слідом за цим ми маємо , твердження нульової ширини , огляд навколо . Ця згрупована конструкція відповідає її вмісту, але не враховується як відповідні символи ( нульова ширина ). Він повертається лише за відповідності чи ні ( твердження ).(?={contents})

Таким чином, іншими словами, регулярний вираз /.+?(?=abc)/означає:

Збігайте будь-які символи якомога менше, доки не знайдено "abc", не рахуючи "abc".


12
Це, ймовірно, не спрацює з розривами рядків, якщо вони повинні бути захоплені.
einord

3
Яка різниця між .+?і .*?
robbie

4
@ robbie0630 +означає 1 або більше, де *означає 0 або більше. Включення / виключення ?заповіту зробить його жадібним або не жадібним.
jinglesthula

2
@ testerjoe2 /.+?(?=abc|xyz)/
JohnWrensby

4
Я помітив, що це не вдається вибрати нічого, якщо шаблон, який ви шукаєте, не існує, натомість, якщо ви використовуєте, ^(?:(?!abc)(?!def).)*ви можете ланцюг, щоб виключити шаблони, які ви не хочете, і він все одно захопить все необхідне, навіть якщо шаблон не існує
Karan Shishoo

122

Якщо ви хочете зафіксувати все до "abc":

/^(.*?)abc/

Пояснення:

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

^ матч початку рядка

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

[1] Причина, чому це потрібно, полягає в тому, що в іншому випадку в наступному рядку:

whatever whatever something abc something abc

за замовчуванням регулярні вирази жадібні , це означає, що вони максимально збігаються. Тому /^.*abc/було б відповідати "все, що б щось не було". Додавання не жадібного кількісного показника ?змушує регулярний вирівнювання відповідати лише "що б там не було".


4
Спасибі, але ваш один робить включати Азбуки в матчі. Іншими словами, отримана відповідність - "що б там не було".
callum

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

Як зазначали @Jred Ng та @Issun, ключ для вирішення такого типу RegEx, як "узгодження всього до певного слова або підрядка" або "відповідність усьому після певного слова або підрядка" називається "твердженням нульової довжини" . Детальніше про них читайте тут.

У вашому конкретному випадку це можна вирішити позитивним поглядом вперед: .+?(?=abc)

Малюнок вартує тисячі слів. Пояснення див. На скріншоті.

Скріншот Regex101


23
.+?(?=abc)копіювальний регекс коштує більше.
Том

Як щодо виключення провідних просторів?
Рой

8

Те, що вам потрібно, - огляньте твердження, як .+? (?=abc) .

Подивитися: Lookahead та Lookbehind Zero-Length твердження

Будьте в курсі, що [abc]це не те саме, що abc. Всередині дужок це не рядок - кожен символ є лише однією з можливостей. Поза дужками вона стає струною.


7

Що стосується регулярного виразів у Java, я вірю також у більшості двигунів, якщо ви хочете включити останню частину, це спрацює:

.+?(abc)

Наприклад, у цьому рядку:

I have this very nice senabctence

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

використовуючи наш регулярний вираз, результат буде: I have this very nice senabc

Перевірте це: https://regex101.com/r/mX51ru/1


4

Я закінчився цим питанням про stackoverflow після пошуку допомоги, щоб вирішити свою проблему, але не знайшов рішення для неї :(

Тому мені довелося імпровізувати ... через деякий час мені вдалося дістати потрібний мені регулярний вираз:

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

Як бачите, мені потрібна була до однієї папки перед папкою "grp-bps", не враховуючи останнього тире. І потрібно було мати принаймні одну папку після папки "grp-bps".

Редагувати

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

.*\/grp-bps\/[^\/]+

6
Немає текстової версії? 🙄
kiradotee

2

Це буде мати сенс щодо регулярного вираження.

  1. Точне слово можна отримати з наступної команди regex:

("(. *?)") / g

Тут ми можемо отримати точне слово у всьому світі, яке належить до подвійних лапок. Наприклад, якщо наш текст пошуку,

Це приклад для слів з подвійним цитуванням

тоді ми отримаємо "подвійне цитування" з цього речення.


Ласкаво просимо до 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)]має зробити трюк.


Вибачте, це не працює. Якщо розмістити abc в дужках, схоже, це не має ніякого значення. Вони досі трактуються як "АБО АБО С".
callum

-1

В $позначає кінець рядка, так що - то , як це повинно працювати: [[^abc]*]$де ви шукаєте що - небудь не закінчується в будь-який ітераціїabc , але вона повинна була б бути в кінці

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.