2
votes

Regex pour extraire les hashtags avec deux parties séparées par des points

J'essaie de créer une expression régulière afin d'extraire du texte à partir de chaînes. Je veux extraire du texte d'urls ou de messages texte normaux, par exemple:

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

OU

Hi #someuser.name, how are you?

Et des deux, je veux extraire exactement # someuser.name depuis le message et # someuser.id depuis l'url. Il peut y avoir beaucoup de ces chaînes à extraire de l'url et des messages.

Mon expression régulière ressemble actuellement à ceci:

endpoint/?userId=#someuser.id

Cela fonctionne bien, sauf un pour un cas et je ne sais pas comment le faire - Par exemple:

Ces chaînes NE DEVRAIENT PAS correspondre: # .id , # .id . Il doit y avoir au moins un caractère entre # et . . Un ou plusieurs espaces entre ces caractères ne doivent pas être mis en correspondance.

Comment puis-je le faire en utilisant mon expression régulière actuelle?


6 commentaires

Essayez String regex = "# [^.] * [^. \\ s] [^.] * (?: \\. \\ w +) *"; . Ou String regex = "# [^.] * [^. \\ s] [^.] * \\. \\ w +";


Veuillez vérifier la deuxième expression régulière du commentaire ci-dessus si vous voulez faire correspondre # et 2 parties séparées par . après.


@ WiktorStribiżew si proche! Il n'y a qu'une seule chaîne qui ne devrait pas être mise en correspondance mais c'est par exemple: # # .id Le caractère '#' est illégal, le hachage signifie seulement qu'il y a une balise à faire correspondre mais il ne peut pas être utilisé comme l'un des caractères spéciaux disponibles


Alors, essayez d'exclure # du premier groupe, "# [^. #] * [^. # \\ s] [^ #.] * \\. \\ w +" < / code>, voir regex101.com/r/Qv8Qnl/1


@ WiktorStribiżew parfait! =) Maintenant, tout fonctionne correctement, merci :)


Heureux de vous aider, a publié une réponse ci-dessous .


4 Réponses :


1
votes

Vous pouvez essayer l'expression régulière suivante:

#someuser.id
#someuser.name

démo

Remarques:

  • supprimez les parenthèses si vous ne souhaitez capturer aucun groupe.
  • dans votre chaîne java regex, vous devez échapper à chaque \
  • cela donne #(\\w+)\\.(\\w+)
  • si l ' id est uniquement composé de chiffres, vous pouvez modifier le deuxième \ w par [0-9ITED
  • si le nom d’utilisateur comprend d’autres caractères que l’alphabet, des chiffres et un trait de soulignement, vous devez changer \ w en une classe de caractères avec tous les caractères autorisés définis explicitement. li >

Exemple de code:

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());
}

sortie:

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


12 commentaires

C'est proche mais il devrait être possible d'utiliser des espaces en valeur entre # et. mais UNIQUEMENT s'il y a d'autres personnages. L'espace est illégal dans le "deuxième groupe" de votre exemple. Donc je peux avoir ces chaînes: # someuser.id, #some user.id MAIS je ne peux pas ceux: # .id, # .id, # someuser.i d


Aussi dans le premier mot entre # et. devrait être possible d'utiliser tous les caractères aussi spéciaux comme () - * etc


@Carath qu'en est-il de #someuser .id avec un espace juste avant le point


l'espace avant le point est possible mais pas après


@Carath pouvez-vous essayer: # ((?: * [\ w \ [\] () * -] + *) +) \. (\ W +)


C'est vraiment proche mais je ne peux pas utiliser maintenant des personnages comme! @% par exemple: # certains% user .id ne correspondent pas, mais lorsque supprimez '%', c'est correct.


@Carath ajoutez-les simplement entre les crochets de l'expression régulière et gardez le - avant le crochet fermant


@Carath # ((?: * [\ w \ [\] () * @!% & {} <> ^ & $ -] + *) +) \. (\ W +)


N'y a-t-il pas quelque chose de plus court pour marquer tous ces caractères au lieu de les ajouter tous?


@Carath vous pouvez écrire ce bloc comme [^ #.] il est plus court, vous acceptez tout sauf l'espace, # et. dans cette partie


@Allan qui correspondrait également à la virgule dans le deuxième cas de test ( # someuser.name, au lieu de # someuser.name ). Dans l'ensemble, les exigences de la question ne sont pas assez claires pour savoir quels caractères sont et ne sont pas autorisés.


@Kevin Cruijssen me laisse le diviser en 2 groupes, le premier groupe est tout entre # et point, le second groupe est tout entre point et TOUT caractère spécial. Premier groupe: il est possible d'avoir tous les caractères spéciaux bien sûr au lieu de points et #. Il est possible d'avoir des espaces mais PAS seulement des espaces et "quelque chose" à l'intérieur peut ne pas être vide donc "# .id" n'est pas non plus possible. Le deuxième groupe peut ne pas avoir de caractères spéciaux - seules les lettres et les chiffres sont possibles ici, également l'espace n'est pas possible dans le deuxième groupe. Si le deuxième groupe a un caractère spécial, cela signifie qu'il y a la fin de la correspondance



0
votes
endpoint/?userId=#someuser.id -> group[0]=someuser and group[1]=id

2 commentaires

Ce n'est pas ce que je veux sans raison. Je ne veux qu'un seul groupe et il devrait être possible d'utiliser des espaces en valeur entre # et. mais UNIQUEMENT s'il y a d'autres personnages. L'espace est illégal dans le "deuxième groupe" de votre exemple. Donc je peux avoir ces chaînes: # someuser.id, #some user.id MAIS je ne peux pas ceux: # .id, # .id, # someuser.i d


pouvez-vous essayer ceci (# \ w +. + \ w *. \ w +) vous obtiendrez # someuser.id, # some user.id mais pas # .id, # .id



1
votes

Les exigences redéfinies sont:

  • Nous recherchons le motif #A.B
  • Un peut être n'importe quoi, sauf pour les espaces uniquement, ni contenir # ou .
  • B ne peut être que des lettres ou des chiffres ASCII normaux

Conversion de ces exigences en une (possible) regex:

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"

Explication:

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()+'"');


3 commentaires

C'est vraiment proche de ce que je veux mais il y a une correspondance qui devrait être mise en correspondance, par exemple: # .id. Il ne devrait pas être possible d'utiliser dans 'A' un seul espace donc # [space] [space] .id correspond maintenant comme correct mais ne devrait pas l'être


@Carath # [space] [space] .id ne correspond pas à mon code ci-dessus .. Ceci est empêché par le + après \\ s . Êtes-vous en train de dire que # [space] [space] .id est autorisé mais pas # [space] .id ? Dans ce cas, vous pouvez supprimer le + . Ou dites-vous que # [tab] .id doit correspondre, mais pas # [space] .id , auquel cas le \\ s (les espaces et tabulations (et les retours à la ligne si l'option multiligne est activée, ce qui n'est pas le cas ici)) peuvent être remplacés par ``? Je ne comprends pas vraiment votre commentaire, pour être honnête.


@KevinCruijssen: oui sans exigences claires, il n'est pas facile d'atteindre "the" bonne réponse



2
votes

Vous pouvez utiliser

#someuser.id
#someuser.name

Voir la démo regex a> et son graphique :

 entrez la description de l'image ici p>

Détails

  • # - un symbole #
  • [^. #] * - zéro ou plusieurs caractères autres que . et #
  • [^. # \\ s] - tout caractère sauf . , # et les espaces
  • [^ #.] * - - zéro ou plusieurs caractères autres que . et #
  • \. - un point
  • \ w + - 1 caractères ou plus de mots (lettres, chiffres ou _ ).

Démo 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)); 
} 

Sortie:

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


1 commentaires

C'est ce que je voulais, merci :)