En expresiones regulares, haga coincidir el final de la cadena o un carácter específico

Resuelto Gary asked hace 12 años • 2 respuestas

Tengo una cuerda. El final es diferente, como index.php?test=1&list=ULo index.php?list=UL&more=1. Lo único que estoy buscando es &list=.

¿Cómo puedo unirlo, ya sea en el medio de la cuerda o al final? Hasta ahora lo tengo [&|\?]list=.*?([&|$]), pero la ([&|$])pieza en realidad no funciona; Estoy tratando de usar eso para hacer coincidir &el final de la cadena, pero el final de la parte de la cadena no funciona, por lo que este patrón coincide con el segundo ejemplo pero no con el primero.

Gary avatar Aug 23 '12 07:08 Gary
Aceptado

Usar:

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

Tenga en cuenta que cuando utiliza una expresión entre corchetes, cada carácter que contiene (con algunas excepciones) se interpretará literalmente. En otras palabras, [&|$]coincide con los caracteres & , |y $.

João Silva avatar Aug 23 '2012 00:08 João Silva

En breve

Cualquier aserción de ancho cero dentro [...]pierde su significado de aserción de ancho cero. [\b]no coincide con el límite de una palabra (coincide con un retroceso o, en POSIX, \o b), coincide con un carácter [$]literal , es un error o, como en el tipo de expresión regular de ECMAScript, cualquier carácter. Lo mismo con las anclas .$[^]\z\Z\A

Puede resolver el problema utilizando cualquiera de los siguientes patrones:

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

Si necesita verificar el anclaje del extremo de la cadena "absoluto" e inequívoco, debe recordar que hay varios tipos de expresiones regulares y se expresa con diferentes construcciones:

[&?]list=(.*?)(?=&|$)  - OK for ECMA regex (JavaScript, default C++ `std::regex`)
[&?]list=(.*?)(?=&|\z) - OK for .NET, Go, Onigmo (Ruby), Perl, PCRE (PHP, base R), Boost, ICU (R `stringr`), Java/Andorid
[&?]list=(.*?)(?=&|\Z) - OK for Python

Coincidencia entre una secuencia de caracteres y un solo carácter o final de cadena (escenario actual)

El .*?([YOUR_SINGLE_CHAR_DELIMITER(S)]|$)patrón ( sugerido por João Silva ) es bastante ineficiente ya que el motor de expresiones regulares comprueba primero los patrones que aparecen a la derecha del patrón de puntos diferidos, y sólo si no coinciden "expande" el patrón de puntos diferidos.

En estos casos se recomienda utilizar la clase de carácter negado (o expresión entre corchetes en la charla POSIX):

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

Ver demostración . Detalles

  • [&?]- una clase de carácter positiva que coincida con &o ?(tenga en cuenta que las relaciones entre caracteres/rangos de caracteres en una clase de caracteres son relaciones O)
  • list=- una subcadena, secuencia de caracteres
  • ([^&]*)- Captura del grupo n.º 1: cero o más *caracteres ( ) distintos de &( [^&]), tantos como sea posible

Comprobar la presencia del delimitador de carácter único final sin devolverlo ni el final de la cadena

La mayoría de los tipos de expresiones regulares (incluido JavaScript a partir de ECMAScript 2018) admiten búsquedas, construcciones que solo devuelven verdadero o falso si los patrones coinciden o no. Son cruciales en caso de que se esperen coincidencias consecutivas que puedan comenzar y terminar con el mismo carácter (consulte el patrón original, puede coincidir con una cadena que comience y termine con &). Aunque no se espera en una cadena de consulta, es un escenario común.

En ese caso, puede utilizar dos enfoques:

  • Una anticipación positiva con una alternancia que contiene una clase de carácter positivo:(?=[SINGLE_CHAR_DELIMITER(S)]|$)
  • Una anticipación negativa con solo una clase de carácter negativo:(?![^SINGLE_CHAR_DELIMITER(S)])

La solución de anticipación negativa es un poco más eficiente porque no contiene un grupo de alternancia que agregue complejidad al procedimiento de comparación. La solución OP sería así

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

o

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

Vea esta demostración de expresiones regulares y otra aquí .

Ciertamente, en caso de que los delimitadores finales sean secuencias de varios caracteres, solo funcionará una solución positiva de anticipación, ya que [^yes]no niega una secuencia de caracteres, sino los caracteres dentro de la clase (es decir, coincide [^yes]con cualquier carácter pero y ).yes

Wiktor Stribiżew avatar Jul 02 '2018 11:07 Wiktor Stribiżew