Шаблон регулярного выражения, который соответствует всем словам, начинающимся со слова с буквы s и заканчивающимся перед словом, начинающимся с буквы s

Я пытаюсь захватить слова в строке так, чтобы первое слово начиналось с s, а регулярное выражение переставало совпадать, если следующее слово также начиналось с s.

Например. У меня есть строка «Стек, код и StackOverflow». Я хочу захватить только «Стек, код и» и не включать «StackOverflow» в соответствие.

Вот что я думаю:

  1. Начните с пробела, за которым следует буква s.
  2. Сопоставьте все, кроме случаев, когда группа представляет собой пробел и s (я использую отрицательный просмотр вперед).

Регулярное выражение, которое я пробовал:

(?<=\s)S[a-z -,]*(?!(\sS))

Я не знаю, как заставить его работать.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
162
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

import re

teststring = " Stack, Code and StackOverflow"
extractText = re.search(r"(\s)[sS][^*\s]*[^sS]*", teststring)

print(extractText[0])

#non-regex solution
listwords = teststring.split(' ')

# non regex solution
start = 0
end = 0
for i,word in enumerate(listwords):
    if word.startswith('s') or word.startswith('S'):
        if start == 0:
            start = i
        else:
            end = i
            break

newstring = " " + " ".join([word for word in listwords[start:end]])
print(newstring)

Выход

 Stack, Code and
 Stack, Code and

Спасибо за помощь. И ваш ответ, и ответ выше решают именно мою проблему.

Izhar 28.11.2022 21:51

Вы можете использовать, например, группу захвата:

(S(?<!\S.).*?)\s*S(?<!\S.)

Объяснение

  • ( Группа захвата 1
    • S(?<!\S.) Соответствуйте S и утверждайте, что слева от S нет границы пробела
    • .*? Сопоставьте любого персонажа, как можно меньше
  • ) Закрыть группу
  • \s* Соответствие необязательным пробельным символам
  • S(?<!\S.) Соответствуйте S и утверждайте, что слева от S нет границы пробела

Посмотрите демонстрацию регулярных выражений и демонстрацию Python.

Пример кода:

import re

pattern = r"(S(?<!\S.).*?)\s*S(?<!\S.)"
s = "Stack, Code and StackOverflow"
m = re.search(pattern, s)
if m:
    print(m.group(1))

Выход

Stack, Code and

Другой вариант, использующий обходной путь, чтобы утвердить S справа и не использовать его, чтобы разрешить несколько совпадений друг за другом:

 S(?<!\S.).*?(?=\s*S(?<!\S.))

Демонстрация регулярных выражений

import re

pattern = r"S(?<!\S.).*?(?=\s*S(?<!\S.))"
s = "Stack, Code and StackOverflow test Stack"
print(re.findall(pattern, s))

Выход

['Stack, Code and', 'StackOverflow test']

@Izhar Вы хотите несколько совпадений в одной строке?

The fourth bird 28.11.2022 22:20

На самом деле я хочу зафиксировать только последнее совпадение в строке. Итак, в приведенном выше примере мне нужен только «тест StackOverflow». Я работаю над извлечением пары акроним-расширение в предложении. Например, если у меня есть предложение: «Можно провести методом капиллярного электрофореза-масс-спектрометрии (КЭ-МС)». Вот мой подход: 1) Начните регулярное выражение с аббревиатуры: (CE-MS) 2) Используя regex lookbehind, сопоставьте все, но остановитесь на первом слове, которое начинается с начального символа в аббревиатуре (в данном случае C). Так что в идеале я бы остановился на слове «капилляр».

Izhar 29.11.2022 03:19

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

Izhar 29.11.2022 03:21

@Izhar Можете ли вы привести пример, когда это не удается?

The fourth bird 29.11.2022 08:58

Я использовал ваш ответ и ответ выше и придумал следующее регулярное выражение. (?<!{p0})(?<= ){p0}[a-z -]*{p1}?[az ]*\s?(?<=){pl}[az ]*\s(?<= )({шаблон}) где {p0} — первый символ в шаблоне, {p1} — второй, а {pl} — последний. В настоящее время он имеет вероятность успеха 92%, но не работает на некоторых входных данных (примеры строк, показанные в окне регулярного выражения) Демонстрация регулярного выражения

Izhar 29.11.2022 14:54

Другие вопросы по теме