Как сопоставить мой шаблон хэштега c? - PullRequest
0 голосов
/ 08 мая 2020

Моя проблема :

У меня есть строка, которая может включать хэштеги (определение см. Ниже), а также последовательность \n (символы \ и n - они представляют собой новую строку, но не управляющий символ (эквивалент последовательности <br> в HTML)

Я хотел бы получить хэштеги (в Python, но вопрос сфокусирован на регулярных выражениях, хотя, если есть лучшее решение в Python, я был бы рад - я все же не добавил тег python, потому что это может слишком уменьшить объем вопроса).

Хэштег определяется как:

  • МОЖЕТ начинаться с пробела или последовательности \n
  • ДОЛЖЕН начинаться с #
  • следующий символ ДОЛЖЕН быть буква или ди git
  • следующий символ ДОЛЖЕН быть буквой, знаком - или знаком _
  • следующие символы МОГУТ быть буквами, цифрами, - или _ (0 или больше)

Мое решение whic h почти работает (заранее извиняюсь, мои навыки регулярного выражения почти отсутствуют, поэтому это может быть очень плохой подход):

#[\w\d][\w\-]*

Пожалуйста, посмотрите мою попытку на regex101 , основанную на в шаблоне выше и в тестовом наборе ниже:

#hashtag some text #hash; #123
 and # not because markdown
# that not
#33 that is not 
either but #3isok 
 or #isok3
astring#andthatshouldnotmatch 
 #hashtagalone
 \n#hashatthebeginning
hello #hashattheend\n
#has_htag 
#ano-the-rone

Мои проблемы :

  • строка 1: #123 совпало, несмотря на ожидаемый второй символ быть буквой или -
  • строка 2: OK
  • строка 3: OK
  • строка 4: #33 была сопоставлена, несмотря на то, что второй символ должен был быть буква или -
  • строка 5: ОК
  • строка 6: ОК
  • строка 7: хэштег был сопоставлен, несмотря на то, что он был приклеен к слову раньше (это не в шаблон, см. ниже дополнительные попытки исправить это)
  • строка 8: ОК
  • строка 9: ОК
  • строка 10: ОК
  • строка 11: _ совпало, несмотря на то, что оно не было в списке допустимых символов (на самом деле будет, но я забыл указать его в шаблоне и обнаружил, что он все равно соответствует)
  • строка 12: ОК

О строке 7: я не добавил возможность пробелов в шаблоне выше, потому что все, что я пробовал, сломало остальное. Я думал, что простого добавления \s* будет достаточно, но я начал сопоставлять конец строк и еще много чего. Я мог бы закончить шаблон с помощью "должно заканчиваться пробелом или последовательностью \n" , но я не знаю, как выполнить операцию ИЛИ, если имеется более одного символа.

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

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Во-первых, чтобы начать шаблон:

МОЖЕТ иметь префикс в виде пробела или последовательности \ n

Итак, шаблон должен начинаться с начала строки, или символ прямо перед ним должен быть пробелом, или он должен быть \n. Вы можете переключаться между этими тремя возможностями следующим образом:

(?:^|(?<=\s)|(?<=\\n))

(не может переключаться между \s и \\n внутри ретроспективного обзора, потому что это сделает его нефиксированной шириной; ретроспективный просмотр должен быть фиксированная ширина почти во всех вариантах)

следующий символ ДОЛЖЕН быть буквой или di git

Если вы хотите только букв и цифры, которые идут сразу после #, тогда не используйте \w, потому что \w также соответствует _. Вместо этого используйте набор символов:

[a-z\d]      # plus case-insensitive flag

следующий символ ДОЛЖЕН быть буквой, знаком - или знаком _

То же самое - просто поместите символы, которые вы хотите включить в набор символов:

[a-z_-]

следующие символы МОГУТ быть буквами, цифрами, - или _ (0 или более)

[a-z\d_-]*

Положите вместе, и вы получите:

(?:^|(?<=\s)|(?<=\\n))#[a-z\d][a-z_-][a-z\d_-]*

https://regex101.com/r/doiLYw/4

1 голос
/ 08 мая 2020

(?:\s|^|\\n)#(\w[-a-zA-Z_][-\w_]*)

Я внес одну модификацию в вашу спецификацию, последнее правило допускает только буквы или цифры после 2-го символа, но ваш самый последний тег в вашем примере кажется мне допустимым, поэтому я разрешил - и _.

Онлайн-тест

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...