2009-04-04 50 views
70

tengo algo como estoExpresión regular que no contiene cierta cadena

aabbabcaabda

para la selección de grupo mínimo envuelto por una tengo este /a([^a]*)a/ que funciona muy bien

Pero tengo problemas con grupos envueltos por aa, donde necesitaría algo como /aa([^aa]*)aa/ que no funciona, y no puedo usar el primero como /aa([^a]*)aa/, porque terminaría en la primera aparición de a, que no quiero.

En general, ¿hay alguna manera, cómo decir no contiene cadena de la misma manera que puedo decir no contiene caracteres con [^a]?

Simplemente dicho, necesito aa seguido de cualquier carácter excepto secuencia aa y luego termina con aa

+0

@SteveChambers ¿Te das cuenta de que esta pregunta tiene más de 7 años y ya tiene una respuesta aceptada? –

+1

Claro, pero como yo lo entiendo ninguno de esos puntos es una razón por la que no debería estar vinculado a un duplicado. –

Respuesta

17

En general es un dolor en escribir una expresión regular no que contiene una cadena en particular. Tuvimos que hacer esto para los modelos de computación: tomas un NFA, que es bastante fácil de definir, y luego lo reduces a una expresión regular. La expresión para las cosas que no contienen "cat" tenía unos 80 caracteres.

Editar: acabo de terminar y sí, es:

aa([^a] | a[^a])aa 

Here es un breve tutorial. Encontré algunos excelentes antes, pero ya no los puedo ver.

+0

¿Conoces algún tutorial que explique esto? –

+0

Hay un buen tutorial de expresiones regulares aquí: http://www.regular-expressions.info/ –

+0

Hola, ¿estás seguro de eso? ¿Alguien puede decirnos si hay algo mal con mi respuesta: http://stackoverflow.com/a/27060278/461444 – AFract

7
/aa([^a]|a[^a])*aa/ 
10

Todo lo que necesita es un cuantificador renuente:

regex: /aa.*?aa/ 

aabbabcaabda => aabbabcaa 

aaaaaabda  => aaaa 

aabbabcaabda => aabbabcaa 

aababaaaabdaa => aababaa, aabdaa 

Usted podría utilizar búsqueda negativa hacia delante, también, pero en este caso es sólo una manera más prolija lograr lo mismo. Además, es un poco más complicado de lo que gpojd llegó a ser. La búsqueda anticipada debe aplicarse en cada posición antes de que el punto pueda consumir el siguiente carácter.

/aa(?:(?!aa).)*aa/ 

En cuanto al enfoque sugerido por Claudiu y finnw, funcionará bien cuando la cadena centinela es sólo dos caracteres de longitud, pero (como reconoció Claudiu) que sea demasiado difícil de manejar para cadenas más largas.

+1

Creo que nuestro camino es el único método que funcionará con una implementación sin retroceso (http: // swtch.com/~rsc/regexp/regexp1.html), pero sí, es terriblemente molesto. Simplemente no sé la expresión regular lo suficiente como para saber acerca de estas cosas anticipadas =). – Claudiu

+0

La mayoría de los sabores regex modernos, especialmente aquellos integrados en lenguajes de programación, son de retroceso, tipo NFA. Incluso JavaScript, uno de los sabores con menos características, admite lookaheads y cuantificadores reacios. http://www.regular-expressions.info/refflavors.html –

186

Por el poder de Google encontré a blogpost from 2007 que da la siguiente expresión regular que coincide con cadena que no lo hacen contiene una determinada subcadena:

^((?!my string).)*$ 

Funciona de la siguiente manera: se busca cero o más (*) caracteres (.) que no comienzan (?!- lookahead negativo) su cadena y estipula que toda la cadena debe estar compuesta por dichos caracteres (utilizando los anclajes^y $). O para decirlo de otra manera:

La cadena completa debe estar formada por caracteres que no comiencen una cadena dada, lo que significa que la cadena no contiene la subcadena dada.

+7

De acuerdo con los documentos, este es un lookahead negativo, no mirar atrás –

+0

(del blog citado) full regexp ref: http://www.regular-expressions.info /refadv.html –

+1

La solución exacta para la pregunta es: '^ aa (?!. * aa. * aa). * aa $' es decir, comienza por ** aa **, mira hacia adelante y descarta las selecciones que siguen con ** [cualquier cosa] aa [cualquier cosa] aa **, y termine por ** aa ** –

2
".*[^(\\.inc)]\\.ftl$" 

En Java esto encontrará todos los archivos que terminan en ".ftl" pero que no terminan en ".inc.ftl", que es exactamente lo que yo quería.

+2

'[]' dividir 'inc' en' i', 'n',' c'. Entonces es falso con ambos '" aiftl ".matches (". * [^ (\\. Inc)] \\. Ftl $ ")' y '" a.inc.ftl ".matches (". * [^(\\. inc)] \\. ftl $ ")'. –

4

I el siguiente código que tuve que reemplazar agrega un parámetro GET a todas las referencias a los archivos JS, EXCEPTO uno.

<link rel="stylesheet" type="text/css" href="/login/css/ABC.css" /> 
<script type="text/javascript" language="javascript" src="/localization/DEF.js"></script> 
<script type="text/javascript" language="javascript" src="/login/jslib/GHI.js"></script> 
<script type="text/javascript" language="javascript" src="/login/jslib/md5.js"></script> 
sendRequest('/application/srvc/EXCEPTION.js', handleChallengeResponse, null); 
sendRequest('/application/srvc/EXCEPTION.js",handleChallengeResponse, null); 

Este es el Matcher utilizado:

(?<!EXCEPTION)(\.js) 

Lo que hace es buscar todas las apariciones de ".js" y si están precedidos por la cadena 'excepción', descarte derivadas de la matriz de resultados Eso se llama mirada negativa detrás. Desde que pasé un día investigando cómo hacerlo, pensé que debería compartirlo.

6

No estoy seguro de que sea una construcción estándar, pero creo que debería echarle un vistazo al "lookahead negativo" (que escribe: "?!", Sin las comillas). Es mucho más fácil que todas las respuestas en este hilo, incluida la aceptada.

Ejemplo: Regex: "^ (?! 123) [0-9] * \ w" captura cualquier cadena que comienza por dígitos seguidos de letras, a menos que si "estos dígitos" son 123.

http://msdn.microsoft.com/en-us/library/az24scfc%28v=vs.110%29.aspx#grouping_constructs (página de Microsoft, pero bastante completo) para lookahead/lookbehind

PD: funciona bien para mí (.Net). Pero si me equivoco con algo, háganoslo saber. Encuentro esta construcción muy simple y efectiva, por lo que estoy sorprendido de la respuesta aceptada.

Cuestiones relacionadas