Поиск хэштегов в тексте - PullRequest
1 голос
/ 21 июня 2019

Да, здесь есть много хэштегов, но ни один из них не соответствует моим потребностям.И никто на самом деле не может решить эту проблему.

Regex должен считать следующие хэштеги действительными:

#validhashtag
#valid_hashtag
 #validhashtag_with_space_before_or_after
#valid_hashtag_chars_öÖäÄüÜß

... и недействительными следующие:

ipsum#notvalid //Not valid: Connected to Word
http://google.com/#results //Not valid: Same as above
#not-valid
#not!valid

Допустимые символы должны быть: aZ, 0-9, öÖäÄüÜß, _

Максимальная длина должна составлять 50 символов.

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

Это то, что я пытался сделать

/([\p{Pc}\p{N}\p{L}\p{Mn}]{1,50})/u

Это работает довольно хорошо, но не учитывает «слово # хэштег» -Проблема.

Ответы [ 2 ]

3 голосов
/ 21 июня 2019

Я думаю, что ваше оригинальное выражение довольно велико, мы просто изменили бы это с помощью:

^\s*#([\p{Pc}\p{N}\p{L}\p{Mn}]{1,50})$

Демо

Тест

$re = '/^\s*#([\p{Pc}\p{N}\p{L}\p{Mn}]{1,50})$/um';
$str = '#validhashtag
#valid_hashtag
 #validhashtag_with_space_before_or_after
#valid_hashtag_chars_öÖäÄüÜß

ipsum#notvalid //Not valid: Connected to Word
http://google.com/#results //Not valid: Same as above
#not-valid
#not!valid';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

// Print the entire match result
var_dump($matches);

выход

array(4) {
  [0]=>
  array(2) {
    [0]=>
    string(13) "#validhashtag"
    [1]=>
    string(12) "validhashtag"
  }
  [1]=>
  array(2) {
    [0]=>
    string(14) "#valid_hashtag"
    [1]=>
    string(13) "valid_hashtag"
  }
  [2]=>
  array(2) {
    [0]=>
    string(41) " #validhashtag_with_space_before_or_after"
    [1]=>
    string(39) "validhashtag_with_space_before_or_after"
  }
  [3]=>
  array(2) {
    [0]=>
    string(35) "#valid_hashtag_chars_öÖäÄüÜß"
    [1]=>
    string(34) "valid_hashtag_chars_öÖäÄüÜß"
  }
}
3 голосов
/ 21 июня 2019

Вы можете использовать любой из двух ниже:

/(?<!\S)#\w+(?!\S)/u
/(?<!\S)#[\w\p{M}\p{Pc}]+(?!\S)/u

См. Демонстрационную версию regex .Если вы хотите ограничить длину части слова, оставьте свой {1,50} квантификатор - /(?<!\S)#\w{1,50}(?!\S)/u.

Также обратите внимание: \w даже с модификатором u не соответствует тем же символам, которые рассматриваются "слово "в .NET, Java, Python re регулярное выражение.Вы можете решить включить другие классы, чтобы заполнить пробел, и использовать [\w\p{M}\p{Pc}]+ вместо просто \w, где \p{M} соответствует любым диакритическим знакам, а \p{Pc} соответствует любой пунктуации соединителя.

Подробности

  • (?<!\S) - пробел или начало строки, необходимые прямо перед
  • # - знак #
  • \w+ - 1+слово chars ( NOTE , если вы хотите ограничить его длину от 1 до 50, замените + на {1,50}) (также обратите внимание, что модификатор u позволяет механизму PCRE соответствовать любым буквам Unicode ицифры с \w сокращением)
  • [\w\p{M}\p{Pc}] - соответствует 1+ знакам слова + всем диакритическим знакам (\p{M}) и пунктуации всех соединителей (\p{Pc}, рассматривается как слово в регулярном выражении .NET)
  • (?!\S) - пробел или конец строки, необходимые сразу после.

PHP демо :

$s = "#validhashtag
#valid_hashtag
 #validhashtag_with_space_before_or_after
#valid_hashtag_chars_öÖäÄüÜß
...and not valid shoulw be:

ipsum#notvalid //Not valid: Connected to Word
http://google.com/#results //Not valid: Same as above
#not-valid
#not!valid";
if (preg_match_all('~(?<!\S)#\w+(?!\S)~u', $s, $matches)) {
   print_r($matches[0]);
}

Вывод:

Array
(
    [0] => #validhashtag
    [1] => #valid_hashtag
    [2] => #validhashtag_with_space_before_or_after
    [3] => #valid_hashtag_chars_öÖäÄüÜß
)
...