Regex: correspondance jusqu'à la première occurrence d'un personnage


358

Je cherche un motif qui correspond à tout jusqu'à la première occurrence d'un caractère spécifique, disons un ";" - un point - virgule .

J'ai écrit ceci:

/^(.*);/

Mais il correspond en fait à tout (y compris le point-virgule) jusqu'à la dernière occurrence d'un point-virgule.


65
/^(.*?);/devrait également fonctionner (cela s'appelle non gourmand ), mais les réponses données en utilisant [^;]*sont meilleures.
Pascal

comment choisiriez-vous tout, après le point-virgule, et non le point-virgule lui-même.
Muhammad Umer

voir cela fonctionne, \w+(?!([^]+;)|;)mais cela ne veut pas pourquoi? .+(?!([^]+;)|;)
Muhammad Umer

1
Pascal, tu aurais dû écrire ça comme réponse!
Sean Kendle

@Pascal Cela convient comme réponse! Merci!
neverMind9

Réponses:


503

Vous avez besoin

/[^;]*/

Le [^;]est une classe de caractères , elle correspond à tout sauf un point-virgule.

Pour citer la perlrepage de manuel:

Vous pouvez spécifier une classe de caractères, en joignant une liste de caractères entre [], qui correspondra à n'importe quel caractère de la liste. Si le premier caractère après le "[" est "^", la classe correspond à tout caractère ne figurant pas dans la liste.

Cela devrait fonctionner dans la plupart des dialectes regex.


La grande partie de cette solution est qu'elle correspond également à la fin de la ligne, par exemple dans mon cas, j'avais foo=bar;baz=bax;bab=bafet elle correspondait bab=bafmême s'il n'y a pas ;exactement ce dont j'ai besoin. Je ne sais pas pourquoi cela fonctionne bien si la spécification dit que tout correspond sauf le symbole cible ...
skryvets


38

/^[^;]*/

Le [^;] dit correspondre à tout sauf un point-virgule. Les crochets sont un opérateur de correspondance d'ensemble, il s'agit essentiellement de faire correspondre n'importe quel caractère de cet ensemble de caractères, ^au début, il s'agit d'une correspondance inverse, donc faites correspondre tout ce qui ne se trouve pas dans cet ensemble.


3
Sachez que le premier ^ de cette réponse donne au regex une signification complètement différente: il fait que l'expression régulière ne recherche que les correspondances commençant au début de la chaîne. Dans ce cas, ce serait effectivement un no-op si vous n'exécutez l'expression régulière qu'une seule fois. Si vous souhaitez rechercher plusieurs correspondances dans une même chaîne, le premier ^ devrait être utilisé.
Dan Breslau

4
Il a dit qu'il voulait tout faire correspondre jusqu'à la première occurrence d'un point-virgule, alors j'ai supposé qu'il voulait dire dès le début de la chaîne.
Glenn Slaven

15

Essayer /[^;]*/

Google regex character classespour plus de détails.



8

exemple de texte:

"this is a test sentence; to prove this regex; that is g;iven below"

Si, par exemple, nous avons l'exemple de texte ci-dessus, l'expression régulière /(.*?\;)/vous donnera tout jusqu'à la première occurrence de point-virgule ( ;), y compris le point-virgule:"this is a test sentence;"


3
il n'est pas nécessaire de s'échapper ;car car ce n'est pas un caractère spécial regex. Le regroupement ()n'est pas également requis. Vous pouvez aller avec/.*?;/
Aliaksei Kliuchnikau

1
Oui, tu as bien raison. l'évasion ressemblait plus à "mieux vaut prévenir que guérir"
poncius

2
C'est la réponse que je cherchais. Alors le ? fait que le match se termine à la première occurrence? Quel est le nom de cette propriété (appelons-la) de l'expression rationnelle?
Parziphal

1
@Parziphal le ?personnage rend le match paresseux (correspondant aussi peu de fois que possible). Pensez aux regex correspondant aux personnages jusqu'au premier point-virgule, puis cela ne va pas plus loin car il abandonne (paresseux;))
derekantrican

5

ce n'est pas une solution regex, mais quelque chose d'assez simple pour la description de votre problème. Divisez simplement votre chaîne et obtenez le premier élément de votre tableau.

$str = "match everything until first ; blah ; blah end ";
$s = explode(";",$str,2);
print $s[0];

production

$ php test.php
match everything until first

5

Cela m'a été très utile car j'essayais de trouver comment faire correspondre tous les caractères d'une balise xml, y compris les attributs. Je rencontrais le problème "correspond à tout jusqu'à la fin" avec:

/<simpleChoice.*>/

mais a pu résoudre le problème avec:

/<simpleChoice[^>]*>/

après avoir lu ce post. Merci a tous.


1
J'avais trouvé qu'il est beaucoup plus efficace d'analyser réellement (chaque langage ou framework a ses propres classes pour cela) html / xml à cause de son format machine, les regex sont pour le langage naturel.
Leon Fedotov

1
Agréable. J'ai utilisé cela pour corriger des documents xml avec des erreurs de syntaxe dans la <!DOCTYPE>balise. Puisque l'analyseur n'a pas pu le gérer.
Martin Schneider

5

Cela correspondra à la première occurrence uniquement dans chaque chaîne et ignorera les occurrences suivantes.

/^([^;]*);*/

3

"/^([^\/]*)\/$/" travaillé pour moi, pour obtenir uniquement les meilleurs "dossiers" d'un tableau comme:

a/   <- this
a/b/
c/   <- this
c/d/
/d/e/
f/   <- this

2

Vraiment un peu triste que personne ne vous ait donné la bonne réponse ...

En regex,? le rend non gourmand. Par défaut, l'expression régulière correspondra autant que possible (gourmand)

Ajoutez simplement un? et il sera non gourmand et correspondra le moins possible!

Bonne chance, j'espère que ça aide.


3
Cela dépend fortement de l' implémentation regex réelle et toutes les implémentations n'ont pas un mode non gourmand.
karatedog

0

Je l'ai trouvé

/^[^,]*,/

fonctionne bien.

',' étant le "délimiteur" ici.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.