Regex: comment faire correspondre n'importe quelle chaîne jusqu'à ce que les espaces, ou jusqu'à ce que la ponctuation suivie par des espaces?
Je suis en train d'écrire une expression régulière qui va trouver les Url dans un texte clair de la chaîne, afin que je puisse les envelopper avec des balises d'ancrage. Je sais qu'il y a les expressions déjà disponibles pour ce, mais je veux créer mon propre, parce que je veux savoir comment il fonctionne.
Depuis, il ne va pas casser quelque chose si ma regex ne parvient pas, mon plan est d'écrire quelque chose de relativement simple. Jusqu'à présent cela signifie que: 1) match "www" ou de "http" au début d'un mot 2) garder correspondance jusqu'à ce que le mot se termine.
Je peux le faire, AFAICT. J'ai ceci: \b(http|www).?[^\s]+
Qui fonctionne sur foo www.example.com bar http://www.example.com
etc.
Le problème est que si je lui donne foo www.example.com, http://www.example.com
il pense que la virgule est une partie de l'URL.
Donc, si je suis pour utiliser une expression pour ce faire, j'ai besoin de changer "...et arrêtez-vous quand vous voyez des espaces" à "...et arrêtez-vous quand vous voyez des espaces ou un morceau de ponctuation à droite avant d'espaces". C'est ce que je ne suis pas sûr de la façon de faire.
À l'heure actuelle, une solution, je suis à la pensée de courir avec est juste d'ajouter un autre test d'appariement de l'URL, puis sur la ligne suivante le déplacement de tous les sournois signe de ponctuation. Ce n'est pas aussi élégant.
Note: je suis en train d'écrire cela en PHP.
De côté: pourquoi remplacer \s
avec \b
dans l'expression ci-dessus ne semble pas fonctionner?
ETA:
Merci à tous!
C'est ce que j'ai fini avec, basé sur l'Explosion des Pilules de conseils:
function add_links( $string ) {
function replace( $arr ) {
if ( strncmp( "http", $arr[1], 4) == 0 ) {
return "<a href=$arr[1]>$arr[1]</a>$arr[2]$arr[3]";
} else {
return "<a href=" . "http://" . $arr[1] . ">$arr[1]</a>$arr[2]$arr[3]";
}
}
return preg_replace_callback( '/\b((?:http|www).+?)((?!\/)[\p{P}]+)?(\s|$)/x', replace, $string );
}
J'ai ajouté un rappel de sorte que tous les liens de commencer par http://, et fait un peu de jongler avec la façon dont il gère la ponctuation.
Ce n'est probablement pas la Meilleure façon de faire les choses, mais il fonctionne. J'ai beaucoup appris à ce sujet dans le dernier peu de temps, mais il y a toujours plus à apprendre!
Merci et merci à vous!
OriginalL'auteur Nick Loewen | 2013-06-05
Vous devez vous connecter pour publier un commentaire.
...est probablement ce que vous allez pour. Je pense que c'est encore imparfaite, mais elle devrait au moins fonctionner pour vos besoins.
De côté: je pense que c'est parce que
\b
correspond à la ponctuation tropOriginalL'auteur Explosion Pills
Vous pouvez réaliser cela avec un anticipation positif affirmation:
Voir ici sur Regexr.
Moyens, le match rien de, mais des espaces
,.!?
OU d'un match,.!?
quand il n'est pas suivie par des espaces.De côté: Un limite de mot n'est pas un caractère ou un ensemble de caractères, vous ne pouvez pas le mettre dans une classe de caractères. C'est une largeur nulle affirmation, c'est la mise en correspondance sur un changement à partir d'un mot à un personnage de caractère non alphabétique. Ici, je crois,
\b
dans une classe de personnage est interprété comme le caractère de retour arrière (la chaîne de la séquence d'échappement).OriginalL'auteur stema
Le problème réside peut-être dans la dot, qui signifie "n'importe quel caractère" dans la regex parler. Vous aurez probablement à y échapper:
Ensuite, le point d'interrogation signifie 0 ou 1, de sorte que vous avez dit "une option de dot" qui n'est pas ce que vous voulez (à droite?):
Maintenant, il ne fait correspondre
http.
etwww.
de sorte que vous devez dire ce que les autres personnages vous laisserai accepter:ou
Alors maintenant, vous êtes en train de dire,
http
ouwww
a-z
ouA-Z
, ne laissez pas un caractère d'espacement- Je ne l'ai pas testé, mais ils ne sont heureusement correct-ish.
De côté (mon prendre sur elle) - le
\s
signifie 'espace'. Le\b
signifie "limite de mot". Le[]
signifie 'un permis de la gamme de caractères'. Le^
signifie 'pas'. Le+
signifie "un ou plus".Quand vous dites
[^\b]+
vous êtes en train de dire "ne pas autoriser les frontières de mot dans cette gamme de caractères, et il doit y avoir un ou plusieurs" et depuis il n'y a rien d'autre là > rien d'autre n'est autorisé > il n'y a pas ou plus > c'est probablement pauses.\b
dans une classe de personnage est interprété comme le caractère de retour arrière (la chaîne de la séquence d'échappement).Le point est facultatif, car après
http
il n'y a pas de point, de sorte qu'il ne correspondra pas à partir de l'adresse http.OriginalL'auteur Ben
Vous devriez essayer quelque chose comme ceci:
OriginalL'auteur NeverHopeless