regex - online - Expresiones regulares: ¿Hay un operador AND?
regex one (12)
Obviamente, puedes usar el |
(¿tubería?) para representar OR
, pero ¿hay una manera de representar AND
también?
Específicamente, me gustaría hacer coincidir los párrafos del texto que contienen TODA una determinada frase, pero sin ningún orden en particular.
¿No es posible en su caso hacer el AND en varios resultados coincidentes? en pseudocódigo
regexp_match(pattern1, data) && regexp_match(pattern2, data) && ...
¿Por qué no usar awk?
Con awk regex AND, OR es tan simple
awk ''/WORD1/ && /WORD2/ && /WORD3/'' myfile
Debe usar lookahead como han dicho algunos de los otros respondedores, pero el lookahead debe tener en cuenta otros caracteres entre su palabra objetivo y la posición de coincidencia actual. Por ejemplo:
(?=.*word1)(?=.*word2)(?=.*word3)
El .*
En el primer lookahead permite que coincida con la cantidad de caracteres que necesita antes de que llegue a "word1". Luego, la posición de coincidencia se restablece y la segunda búsqueda anticipada busca "word2". Reinicie de nuevo, y la parte final coincide con "word3"; ya que es la última palabra que está verificando, no es necesario que esté en una búsqueda anticipada, pero no duele.
Para hacer coincidir un párrafo completo, debe anclar la expresión regular en ambos extremos y agregar un final .*
Para consumir los caracteres restantes. Usando la notación estilo Perl, eso sería:
/^(?=.*word1)(?=.*word2)(?=.*word3).*$/m
El modificador ''m'' es para modo multilínea; permite que ^
y $
coincidan en los límites de los párrafos ("límites de línea" en expresiones regulares). Es esencial en este caso que no uses el modificador ''s'', que permite que el metacarácter punto coincida con las nuevas líneas, así como con todos los demás caracteres.
Finalmente, desea asegurarse de que coincida con palabras completas y no solo con fragmentos de palabras más largas, por lo que necesita agregar límites de palabras:
/^(?=.*/bword1/b)(?=.*/bword2/b)(?=.*/bword3/b).*$/m
El operador AND está implícito en la sintaxis RegExp.
El operador OR tiene que ser especificado con una tubería.
El siguiente RegExp:
var re = /ab/;
significa la letra a
y la letra b
.
También funciona con grupos:
var re = /(co)(de)/;
significa el grupo co
y el grupo de
.
Reemplazar el AND (implícito) con un OR requeriría las siguientes líneas:
var re = /a|b/;
var re = /(co)|(de)/;
El orden siempre está implícito en la estructura de la expresión regular. Para lograr lo que desea, deberá hacer coincidir la cadena de entrada varias veces con diferentes expresiones.
Lo que quieres hacer no es posible con una sola expresión regular.
Mira este ejemplo:
Tenemos 2 regexps A y B y queremos coincidir con ambos, por lo que en pseudo-código se ve así:
pattern = "/A AND B/"
Se puede escribir sin usar el operador AND así:
pattern = "/NOT (NOT A OR NOT B)/"
en PCRE:
"/^(^A|^B)/"
regexp_match(pattern,data)
Podría canalizar su salida a otro regex. Usando grep, podrías hacer esto:
grep A | grep B
Puedes hacerlo con una expresión regular, pero probablemente querrás algo más. Por ejemplo, use varias expresiones regulares y combínelas en una cláusula if.
Puede enumerar todas las permutaciones posibles con una expresión regular, como esto (coincide con a, byc en cualquier orden):
(abc)|(bca)|(acb)|(bac)|(cab)|(cba)
Sin embargo, esto hace una expresión regular muy larga y probablemente ineficiente, si tiene más de un par de términos.
Si está utilizando alguna versión extendida de expresiones regulares, como Perl o Java, tienen mejores maneras de hacerlo. Otras respuestas han sugerido el uso de una operación de búsqueda anticipada positiva.
Si usa expresiones regulares de Perl, puede usar lookahead positivo:
Por ejemplo
(?=[1-9][0-9]{2})[0-9]*[05]/b
Serían números mayores de 100 y divisibles por 5.
Usa Y fuera de la expresión regular. En PHP, el operador de búsqueda anticipada no parecía funcionar para mí, en su lugar usé esto
if( preg_match("/^.{3,}$/",$pass1) && !preg_match("//s{1}/",$pass1))
return true;
else
return false;
La expresión regular anterior coincidirá si la longitud de la contraseña es de 3 caracteres o más y no hay espacios en la contraseña.
Use una expresión regular que no consume.
La notación típica (es decir, Perl / Java) es:
(?=
expr )
Esto significa "coincide con expr, pero después de eso, continúe coincidiendo en el punto de coincidencia original".
Puedes hacer tantos de estos como quieras, y esto será un "y". Ejemplo:
(?=match this expression)(?=match this too)(?=oh, and this)
Incluso puede agregar grupos de captura dentro de las expresiones que no consumen si necesita guardar algunos de los datos en ellos.
Además de la respuesta aceptada.
Le proporcionaré algunos ejemplos prácticos que aclararán las cosas a algunos de ustedes. Por ejemplo, digamos que tenemos esas tres líneas de texto:
[12/Oct/2015:00:37:29 +0200] // only this + will get selected
[12/Oct/2015:00:37:x9 +0200]
[12/Oct/2015:00:37:29 +020x]
Ver demo aquí DEMO
Lo que queremos hacer aquí es seleccionar el signo + pero solo si es después de dos números con un espacio y si es antes de cuatro números. Esas son las únicas restricciones. Usaríamos esta expresión regular para lograrlo:
''~(?<=/d{2} )/+(?=/d{4})~g''
Tenga en cuenta que si separa la expresión le dará resultados diferentes.
O quizás quieras seleccionar texto entre etiquetas ... ¡pero no las etiquetas! Entonces podrías usar:
''~(?<=<p>).*?(?=<//p>)~g''
para este texto:
<p>Hello !</p> <p>I wont select tags! Only text with in</p>
Ver demo aquí DEMO