Regex: combina todo menos un patrón específico

310

Necesito una expresión regular capaz de coincidir con todo menos una cadena que comience con un patrón específico (específicamente index.phpy lo que sigue, como index.php?id=2342343)

pistacho
fuente
¿Y qué patrón específico quieres que no coincida?
Dominic Rodger
2
¿Hay alguna razón por la que no puede coincidir con su patrón y no hacer algo si la cadena coincide con eso?
Thomas Owens
@ThomasOwens: Depende. Depende de qué parte de la expresión se negará. Si se va a negar toda la expresión, entonces tienes un punto. Por ejemplo, si desea codificar "si la cadena no contiene 'Bruce' como una subcadena, entonces haga algo", usaría simplemente / Bruce /, y colocaría la negación en la declaración if, fuera de la expresión regular . Pero podría ser que le gustaría negar alguna subexpresión. Digamos que estás buscando algo como nombre, apellido, donde el nombre es Bruce, y el apellido lo es todo excepto XYZ, donde XYZ es el apellido de alguna celebridad llamada Bruce.
mathheadinclouds

Respuestas:

250

No es un experto en expresiones regulares, pero creo que podría usar una búsqueda negativa desde el principio, por ejemplo ^(?!foo).*$, no debería coincidir con nada que comience desde el principio foo.

Cat Plus Plus
fuente
77
Con grep use -P para habilitar la búsqueda anticipada.
Seppo Enarvi
Si el comportamiento deseado no coincide con "foo" o "bar", verifique esta respuesta: stackoverflow.com/a/2404330/874824
dave_k_smith
15
Esta respuesta es incorrecta, una prueba rápida lo demuestra. Creo que lo que quisiste decir es ^((?!foo).)*$( stackoverflow.com/a/406408/3964381 )
gilad mayani
44
¿Podría explicar los símbolos que utilizó y por qué los utilizó?
Rotimi-best
339

Regex: coincide con todo menos :

Nota de demostración : la nueva línea \nse usa dentro de las clases de caracteres negadas en las demostraciones para evitar el desbordamiento de coincidencias a las líneas vecinas. No son necesarios al probar cadenas individuales.

Nota de anclaje : en muchos idiomas, use \Apara definir el inicio inequívoco de la cadena y \z(en Python \Z, en JavaScript, $está bien) definir el final de la cadena.

Nota de puntos : en muchos sabores (pero no en POSIX, TRE, TCL), .coincide con cualquier carácter excepto un carácter de nueva línea . Asegúrese de utilizar el modificador DOTALL correspondiente ( /sen PCRE / Boost / .NET / Python / Java y /men Ruby) para .que coincida con cualquier carácter, incluida una nueva línea.

Nota de barra invertida : en los lenguajes donde tiene que declarar patrones con cadenas C que permiten secuencias de escape (como \npara una nueva línea), debe duplicar las barras invertidas que escapan caracteres especiales para que el motor pueda tratarlos como caracteres literales (por ejemplo, en Java, world\.será declarado como "world\\.", o use una clase de caracteres:) "world[.]". Utilice literales de cadena sin formato (Python r'\bworld\b'), literales de cadena textuales de C # @"world\."o anotaciones literales de cadena / regex /world\./.

Wiktor Stribiżew
fuente
Genial escribir! Para el caso de "una cadena (no) igual a alguna cadena", con el ejemplo de ^(?!foo$), ¿por qué el signo de dólar debe estar entre paréntesis para que la expresión funcione? Esperaba ^(?!foo)$dar los mismos resultados, pero no es así.
Grant Humphries
3
@GrantHumphries: cuando el $ancla está dentro de la búsqueda anticipada, es parte de la condición, parte de esa afirmación de ancho cero . Si estuviera afuera, como adentro ^(?!foo)$, será parte del patrón de consumo que requiere el final de la cadena justo después del inicio de la cadena, lo que hace que la búsqueda anticipada negativa sea irrelevante ya que siempre devolverá verdadero (no puede haber ningún texto después del final de la cadena) , mucho menos foo). Entonces, ^(?!foo$)coincide con el inicio de una cadena que no se sigue con la fooque se sigue con el final de la cadena. ^(?!foo)$coincide con una cadena vacía.
Wiktor Stribiżew
@ robots.txt Por favor, elimine estos comentarios. Estás haciendo una pregunta XY. Las clases de personajes están destinadas a unir caracteres individuales, no hay forma de definir una secuencia de caracteres con ellos. Probablemente debería encontrar la subcadena entre el inicio de una cadena y la primera aparición de coto lan, y eliminar la coincidencia, como regex.replace(myString, "^.*?(?:cot|lan)\s*", "").
Wiktor Stribiżew
Querido Wiktor Has cerrado mi pregunta pero tu respuesta vinculada falla. He actualizado mi pregunta stackoverflow.com/questions/60004380/…
MonsterMMORPG
Por ejemplo, su respuesta vinculada falla en este ejemplo "paquetes ing <! - y página web <! - asdasasdas -> los editores ahora usan -> Lorem Ipsum"
MonsterMMORPG
259

Puede poner un ^al comienzo de un conjunto de caracteres para que coincida con cualquier cosa que no sean esos caracteres.

[^=]*

coincidirá con todo menos =

Firsh - LetsWP.io
fuente
55
Eso es cierto, pero solo procesa un personaje a la vez. Si desea excluir una secuencia de dos o más caracteres, debe usar la búsqueda anticipada negativa como dijeron los otros respondedores.
Alan Moore
solución perfecta para eliminar cualquier carácter no deseado, excepto aquellos en el patrón. gracias
Sirmyself
@Alan, "... tienes que usar una mirada negativa hacia adelante ..." es incorrecto, pero no deberíamos ser demasiado duros contigo porque Wiktor no publicó su respuesta, lo que muestra por qué, hasta 2016.
Cary Swoveland
6

Simplemente coincida y /^index\.php/luego rechace lo que coincida.


fuente
Quizás escrito str !~ /\Aindex\.php/.
Cary Swoveland
6

En python:

>>> import re
>>> p='^(?!index\.php\?[0-9]+).*$'
>>> s1='index.php?12345'
>>> re.match(p,s1)
>>> s2='index.html?12345'
>>> re.match(p,s2)
<_sre.SRE_Match object at 0xb7d65fa8>
AJ
fuente
3
Eso rechazará "index_php" o "index # php".
1

Necesito un poder expresión regular para que coincida con todo , pero excepto una cadena que comienza con index.php un patrón específico (en concreto index.php y lo que sigue, como index.php? Id = 2342343)

Utilice el método Exec

    let match,
        arr = [],
        myRe = /([\s\S]+?)(?:index\.php\?id.+)/g;

    var str = 'http://regular-viragenia/index.php?id=2342343';

    while ((match = myRe.exec(str)) != null) {
         arr.push(match[1]);
    } 
    
    console.log(arr);

var myRe = /([\s\S]+?)(?:index\.php\?id=.+)/g;
var str = 'http://regular-viragenia/index.php?id=2342343';
var matches_array = myRe.exec(str);
console.log(matches_array[1]);

U otro partido

let match,
            arr = [],
            myRe = /index.php\?id=((?:(?!index)[\s\S])*)/g;

        var str = 'http://regular-viragenia/index.php?id=2342343index.php?id=111index.php?id=222';

        while ((match = myRe.exec(str)) != null) {
             arr.push(match[1]);
        } 

        console.log(arr);

Юрий Светлов
fuente
-13

¿Qué tal no usar regex:

// In PHP
0 !== strpos($string, 'index.php')
Percutio
fuente
11
El OP solicitó específicamente una expresión regular ... ¡No estoy seguro de que esto ayude! (Puede estar usando grepen la línea de comandos, por ejemplo, o Perl / Python / cualquier otro idioma, o un comando "Ejecutar esta expresión regular para cada línea" en un editor de texto, etc.)
rinogo