web-dev-qa-db-fra.com

Dans l'expression régulière, correspond à la fin de la chaîne ou à un caractère spécifique

J'ai une chaîne. La fin est différente, comme index.php?test=1&list=UL Ou index.php?list=UL&more=1. La seule chose que je recherche est &list=.

Comment puis-je le faire correspondre, que ce soit au milieu de la chaîne ou à la fin? Jusqu'à présent, j'ai [&|\?]list=.*?([&|$]), mais la partie ([&|$]) Ne fonctionne pas réellement; J'essaie de l'utiliser pour faire correspondre soit & Soit la fin de la chaîne, mais la fin de la partie chaîne ne fonctionne pas, donc ce modèle correspond au deuxième exemple mais pas au premier.

34
Gary

Utilisation:

/(&|\?)list=.*?(&|$)/

Notez que lorsque vous utilisez une expression entre crochets, chaque caractère qu'elle contient (avec certains exceptions) va être interprété littéralement. En d'autres termes, [&|$] correspond aux caractères &, |, et $.

53
João Silva

En bref

Toutes les assertions de largeur nulle à l'intérieur de [...] Perdent leur signification d'une assertion de largeur nulle. [\b] Ne correspond pas à une limite de Word (il correspond à un retour arrière, ou, dans POSIX, \ Ou b), [$] Correspond à un littéral $ Car, [^] Est soit une erreur, soit, comme dans la version regex ECMAScript, n'importe quel caractère. Idem avec \z, \Z, \A Ancres.

Vous pouvez résoudre le problème en utilisant l'un des modèles ci-dessous:

[&?]list=([^&]*)
[&?]list=(.*?)(?=&|$)
[&?]list=(.*?)(?![^&])

Correspondance entre une séquence de caractères et un seul caractère ou fin de chaîne (scénario actuel)

Le modèle .*?([YOUR_SINGLE_CHAR_DELIMITER(S)]|$) ( suggéré par João Silva ) est plutôt inefficace car le moteur d'expression régulière vérifie d'abord les modèles qui apparaissent à droite du modèle de point paresseux, et seulement s'ils le font ne correspond pas à "étendre" le motif de points paresseux.

Dans ces cas, il est recommandé d'utiliser classe de caractères niés (ou expression entre crochets dans la conversation POSIX):

[&?]list=([^&]*)

Voir démo . Détails

  • [&?] - une classe de caractères positive correspondant à & Ou ? (Notez que les relations entre les caractères/plages de caractères dans une classe de caractères sont OR des relations)
  • list= - une sous-chaîne, séquence de caractères
  • ([^&]*) - Capture du groupe # 1: zéro ou plusieurs (*) Caractères autres que & ([^&]), Autant que possible

Vérification de la présence du délimiteur de caractère unique de fin sans le renvoyer ni la fin de la chaîne

La plupart des versions regex (y compris JavaScript commençant par ECMAScript 2018) prennent en charge les contournements, les constructions qui ne renvoient true ou false que si les modèles correspondent ou non. Ils sont cruciaux dans le cas où des correspondances consécutives pouvant commencer et se terminer avec le même caractère sont attendues (voir le modèle d'origine, il peut correspondre à une chaîne commençant et se terminant par &). Bien qu'il ne soit pas prévu dans une chaîne de requête, il s'agit d'un scénario courant.

Dans ce cas, vous pouvez utiliser deux approches:

  • Une anticipation positive avec une alternance contenant une classe de caractères positifs: (?=[SINGLE_CHAR_DELIMITER(S)]|$)
  • Un lookahead négatif avec juste une classe de caractères négatifs: (?![^SINGLE_CHAR_DELIMITER(S)])

La solution d'anticipation négative est un peu plus efficace car elle ne contient pas de groupe d'alternance qui ajoute de la complexité à la procédure de correspondance. La solution OP ressemblerait à

[&?]list=(.*?)(?=&|$)

ou

[&?]list=(.*?)(?![^&])

Voir cette démo regex et ne autre ici .

Certes, dans le cas où les délimiteurs de fin sont des séquences multi-caractères, seule une solution d'anticipation positive fonctionnera puisque [^yes] Ne nie pas une séquence de caractères, mais les caractères à l'intérieur de la classe (c'est-à-dire [^yes] Correspondent à n'importe quel caractère mais y, e et s).

2
Wiktor Stribiżew