Regex: spécifiez "espace ou début de chaîne" et "espace ou fin de chaîne"

127

Imaginez que vous essayez de faire correspondre le modèle "stackoverflow".

Vous voulez ce qui suit:

 this is stackoverflow and it rocks [MATCH]

 stackoverflow is the best [MATCH]

 i love stackoverflow [MATCH]

 typostackoverflow rules [NO MATCH]

 i love stackoverflowtypo [NO MATCH]

Je sais comment analyser stackoverflow s'il a des espaces sur les deux sites en utilisant:

/\s(stackoverflow)\s/

Idem avec si c'est au début ou à la fin d'une chaîne:

/^(stackoverflow)\s/

/\s(stackoverflow)$/

Mais comment spécifier «espace ou fin de chaîne» et «espace ou début de chaîne» en utilisant une expression régulière?

anonyme
la source

Réponses:

172

Vous pouvez utiliser l'un des éléments suivants:

\b      #A word break and will work for both spaces and end of lines.
(^|\s)  #the | means or. () is a capturing group. 


/\b(stackoverflow)\b/

De plus, si vous ne souhaitez pas inclure l'espace dans votre match, vous pouvez utiliser lookbehind / aheads.

(?<=\s|^)         #to look behind the match
(stackoverflow)   #the string you want. () optional
(?=\s|$)          #to look ahead.
Jacob Eggers
la source
8
\best une assertion de largeur nulle; il ne consomme jamais de caractères. Il n'est pas nécessaire de l'envelopper dans un lookaround.
Alan Moore
2
Notez que dans la plupart des implémentations de regexp, \best ASCII standard uniquement , c'est - à - dire, pas de support unicode. Si vous avez besoin de faire correspondre des mots Unicode, vous n'avez pas d'autre choix que de l'utiliser à la place: stackoverflow.com/a/6713327/1329367
Mahn
4
Le moyen le plus simple d'exclure la sélection de groupe du match est(?:^|\s)
user2426679
7
pour python, remplacez (?<=\s|^)par (?:(?<=\s)|(?<=^)). Sinon, vous obtenezerror: look-behind requires fixed-width pattern
user2426679
4
Le \bconsidérerait d'autres caractères - tels que " ." comme des séparateurs de mots, alors que le demandeur a spécifiquement dit "espace". La solution de @ gordy semble meilleure.
Mikhail T.
65

(^|\s)correspondrait à l'espace ou au début de la chaîne et ($|\s)à l'espace ou à la fin de la chaîne. Ensemble c'est:

(^|\s)stackoverflow($|\s)
Gordy
la source
4
c'est le seul qui fonctionne pour moi. merci @gordy
robsonrosa
2
Si vous utilisez ce motif pour remplacer, n'oubliez pas de conserver les espaces dans le résultat remplacé en le remplaçant par le motif $1string$2.
Mahn
C'est le seul qui fonctionne pour moi aussi. Les limites de mots ne semblent jamais faire ce que je veux. D'une part, ils correspondent à certains caractères en plus des espaces (comme des tirets). Cela a résolu le problème pour moi parce que j'avais essayé de mettre $et ^dans une classe de personnages, mais cela montre qu'ils peuvent simplement être placés dans un groupe de motifs régulier.
felwithe
17

Voici ce que j'utiliserais:

 (?<!\S)stackoverflow(?!\S)

En d'autres termes, correspond à "stackoverflow" s'il n'est pas précédé d'un caractère non-espace et non suivi d'un caractère non-espace.

C'est plus net (IMO) que l'approche "espace ou ancre", et cela ne suppose pas que la chaîne commence et se termine par des caractères de mot comme le fait l' \bapproche.

Alan Moore
la source
1
bonne explication sur pourquoi utiliser cela. J'aurais choisi ceci mais la chaîne testée est TOUJOURS une seule ligne.
anonymous-one
7

\b correspond aux limites des mots (sans réellement correspondre à aucun caractère), donc ce qui suit devrait faire ce que vous voulez:

\bstackoverflow\b
Andrew Clark
la source
Pour Python, il est utile de lui spécifier une chaîne brute , par exemplemystr = r'\bstack overflow\b'
Acumenus