#python #regex
Вопрос:
У меня есть регулярное (?<=^|(?<=[^a-zA-Z0-9-_.]))@([A-Za-z] [A-Za-z0-9-_] )(?!w)
выражение .
Учитывая строку @first@nope @second@Hello @my-friend, email@ whats.up@example.com @friend
, что я могу сделать, чтобы исключить строки @first
, и @second
поскольку они сами по себе не являются целыми словами ? Другими словами, исключите их, так как за ними следует @ .
Комментарии:
1. ДА. Я хочу получить
['my-friend', 'friend']
Ответ №1:
Вы можете использовать
(?<![a-zA-Z0-9_.-])@(?=([A-Za-z] [A-Za-z0-9_-]*))1(?![@w])
(?a)(?<![w.-])@(?=([A-Za-z][w-]*))1(?![@w])
Смотрите демонстрацию регулярных выражений. Подробные сведения:
(?<![a-zA-Z0-9_.-])
— отрицательный внешний вид, соответствующий местоположению, которому непосредственно не предшествуют цифры ASCII , буквы_
.
и-
@
— а@
чар(?=([A-Za-z] [A-Za-z0-9_-]*))
— положительный внешний вид с группой захвата внутри, которая захватывает одну или несколько букв ASCII, а затем ноль или более букв ASCII, цифр-
или_
символов1
— значение группы 1 (обратные ссылки являются атомарными, возврат через них не допускается)(?![@w])
— отрицательный указатель, который не соответствует, если есть символ слова (буква, цифра или_
) или@
символ непосредственно справа от текущего местоположения.
Обратите внимание, что я ставлю дефисы в конце классов персонажей, это лучшая практика.
В (?a)(?<![w.-])@(?=([A-Za-z][w-]*))1(?![@w])
альтернативе используются классы сокращенных символов и (?a)
встроенный модификатор (эквивалент re.ASCII
/ re.A
w
), который соответствует только символам ASCII (как в оригинальной версии). Удалите (?a)
, если вы планируете сопоставлять какие-либо цифры/буквы Юникода.
Комментарии:
1. Спасибо, это работает. Можете ли вы объяснить, чем он отличается от моего ?
2. @ImportError Два основных отличия: 1) окончательный внешний вид не работает, если справа есть a
@
, 2) основная часть выполнена атомарной , так что окончательный внешний вид был запущен только один раз, и если он не сработает, это не может привести к возврату в основную часть шаблона. Первое, что бросается в глаза, — это просто усовершенствование.3. Я думаю
(?<![w.-])@(?=([A-Za-z] [w-]*))1(?![@w])
, это тоже сработало бы?4. @rv.kvetch Я обновил ответ.
5.@rv.kvetch Просто хотел объяснить, почему используется атомарный подход: в
@my-friend-@friend
строке не должно быть найдено совпадения, так как-
это часть слова, которое вы хотите извлечь , и если вы удалите атомарный эквивалент и используете(?<![w.-])@([A-Za-z][w-]*)(?![@w])
, вы получите@my-friend
совпадение.
Ответ №2:
Другой вариант-указать границу пробела слева и не указывать символ слова или знак @ справа.
(?<!S)@([A-Za-z] [w-] )(?![@w])
Шаблон совпадает:
(?<!S)
Отрицательный взгляд назад, не утверждайте, что символ без пробелов слева@
Совпадение буквально([A-Za-z] [w-] )
Захватите группу 1, сопоставьте 1 символов A-Za-z, а затем 1 словесных символов или-
(?![@w])
Отрицательный внешний вид, утверждение не @ или символ слова справа
Демонстрация регулярных выражений
Или сопоставьте границу без слов B
перед @ вместо поиска.
B@([A-Za-z] [w-] )(?![@w])