Regex для извлечения хэштегов с двумя разделенными точками частями - PullRequest
2 голосов
/ 29 мая 2019

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

endpoint/?userId=#someuser.id

OR

Hi #someuser.name, how are you?

И из обоих я хочу извлечь #someuser.name из сообщения и #someuser.id из URL. Может быть много таких строк для извлечения из URL и сообщений.

Мое регулярное выражение в настоящее время выглядит так:

(#[^\.]+?\.)([^\W]\w+\b)

Работает нормально, кроме одного на один случай, и я не знаю, как это сделать - например ::

Эти строки НЕ ДОЛЖНЫ совпадать: # .id, #.id. Между # и . должен быть хотя бы один символ. Один или несколько пробелов между этими символами не должны совпадать.

Как я могу сделать это, используя мое текущее регулярное выражение?

Ответы [ 4 ]

2 голосов
/ 29 мая 2019

Вы можете использовать

String regex = "#[^.#]*[^.#\\s][^#.]*\\.\\w+";

См. regex demo и его график :

enter image description here

Подробности

  • # - символ #
  • [^.#]* - ноль или более символов, отличных от .и #
  • [^.#\\s] - любой символ, кроме ., # и пробел
  • [^#.]* - - ноль или более символов, отличных от . и #
  • \. - точка
  • \w+ - 1+ слова (буквы, цифры или _).

Демонстрация Java:

String s = "# #.id\nendpoint/?userId=#someuser.id\nHi #someuser.name, how are you?";
String regex = "#[^.#]*[^.#\\s][^#.]*\\.\\w+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(s);
while (matcher.find()){
    System.out.println(matcher.group(0)); 
} 

Выход:

#someuser.id
#someuser.name
1 голос
/ 29 мая 2019

Переопределенные требования:

  • Ищем шаблон #A.B
  • A может быть чем угодно, кроме только пробелов и не может содержать # или .
  • B могут быть только обычными ASCII-буквами или цифрами

Преобразование этих требований в (возможное) регулярное выражение:

#[^.#]+((?<!#\\s+)\\.)[A-Za-z0-9]+

Пояснение:

#[^.#]+((?<!#\\s+)\\.)[A-Za-z0-9]+  # The entire capture for the Java-Matcher:
#                                   #  A literal '#' character
 [^.#]+                             #  Followed by 1 or more characters which are NOT '.' nor '#'
       (          \\.)              #  Followed by a '.' character
        (?<!     )                  #  Which is NOT preceded by (negative lookbehind):
            #                       #   A literal '#'
             \\s+                   #   With 1 or more whitespaces
                      [A-Za-z0-9]+  #  Followed by 1 or more alphanumeric characters
                                    #  (PS: \\w+ could be used here if '_' is allowed as well)

Код теста:

String input = "endpoint/?userId=#someuser.id Hi #someuser.name, how are you? # .id #.id %^*#@*(.H(@EH Ok, # some spaces here .but none here #$p€©ï@l.$p€©ï@l that should do it..";
System.out.println("Input: \""+ input + '"');

System.out.println("Outputs: ");
java.util.regex.Matcher matcher = java.util.regex.Pattern.compile("#[^.#]+((?<!#\\s+)\\.)[A-Za-z0-9]+")
                                                         .matcher(input);
while(matcher.find())
  System.out.println('"'+matcher.group()+'"');

Попробуйте онлайн.

Какие выходы:

Input: "endpoint/?userId=#someuser.id Hi #someuser.name, how are you? # .id #.id %^*#@*(.H(@EH Ok, # some spaces here .but none here #$p€©ï@l.$p€©ï@l that should do it.."
Outputs: 
"#someuser.id"
"#someuser.name"
"#@*(.H"
"# some spaces here .but"
1 голос
/ 29 мая 2019

Вы можете попробовать следующее регулярное выражение:

#(\w+)\.(\w+)

демо

Примечания:

  • удалите скобки, если вы не хотите захватывать какую-либо группу.
  • в строке Java Regex вам нужно экранировать каждые \
  • это дает #(\\w+)\\.(\\w+)
  • если id состоит только из чисел, вы можете изменить второе \w на [0-9]
  • если username включает в себя другие символы, кроме алфавита, цифр и подчеркивания, вы должны изменить \w на класс символов со всеми разрешенными символами, определенными явно.

Пример кода:

String input = "endpoint/?userId=#someuser.id Hi #someuser.name, how are you? # .id, #.id.";
Matcher m = Pattern.compile("#(\\w+)\\.(\\w+)").matcher(input);
while (m.find()) {
    System.out.println(m.group());
}

выход:

#someuser.id
#someuser.name
0 голосов
/ 29 мая 2019
#(\w+)[.](\w+)

результаты двух групп, например

endpoint/?userId=#someuser.id -> group[0]=someuser and group[1]=id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...