Búsqueda avanzada en Ingrid
Sintaxis de búsqueda reducida y sintaxis mongoDB
Se pueden usar comandos del lenguaje de búsqueda en BD de 4 formas distintas:
- en el campo de Búsqueda en lenguaje natural de la zona superior derecha de cualquier página de la aplicación, si la base de precios o proyecto están indizados.
- en la Búsqueda general de BD (Menú > Proyecto > Búsquedas)
- en conceptos de clase Búsqueda
- en las funciones de Procedimientos javascript que admiten una búsqueda reducida de Ingrid o directamente un find() de mongoDB.
Normalmente esta sintaxis de búsqueda incluso, la simplificada de Ingrid, sólo es usada por administradores, no por el usuario de perfil habitual.
IMPORTANTE: Si en el campo que admite un comando de búsqueda se encuentra un objeto entre llaves { }, se considera una búsqueda find() directamente contra el motor de BD mongoDB, con su sintaxis y el formato: {find:{}, data:{}, sort:{}, limit...}. se puede consultar la referencia en: Mongo find()
También se admite un formato find como {cla:'tarpre', ope:'ope.IOA' }
En BD es muy raro que haya un campo con un valor null grabado, porque el interface elimina estos campos al asignarles ese valor, pero a través de script o al producirse un error de referencias u otros casos, puede existir. Para buscarlos no basta el lenguaje abreviado, hay que buscarlos con un find como {cla:'tarpre', ope:null}. Para los administradores, en el campo JSON de un documento mongodb se visualizarían estos campos null.
Esta sintaxis también permite buscar objetos o listas vacías como: {plis:{}} o {desl:[]} (es decir, cualquier concepto con pliegos pero nulos, o una lista de descompuestos vacía).
Se pueden unir varias condiciones (operador AND) separándolas con espacio en blanco, o hacer una condición OR con una barra vertical ( | ), sólo entre dos campos, no se pueden encadenar condiciones OR, ni anidarlas.
Hay un apartado con el detalle de la sintaxis en expresiones regulares de búsqueda PCRE (las de Perl también usadas en mongoDB).
IMPORTANTE: Siempre que se realiza una búsqueda con ordenación, la recuperación de elementos en la lista necesita obligatoriamente un campo indizado, y para garantizarlo, si no hay otro, ponemos el campo _id. Por tanto, si no se ordena, ni siquiera se ordena por _id por defecto, para evitar ordenaciones innecesarias, pero si por ejemplo, se ordena por el campo resumen (res), también, a igualdad de resumen, se ordenará por campo _id.
ATENCIÓN A ESTOS CASOS:
1. La comparación del contenido entre dos campos se tiene que hacer con
la cláusula where, como:
o
cla=act where=this.fecini==this.fecfin
cla=act where=obj.fecini>obj.fecfin
2. las búsquedas de tipo NOT IN (y sobre todo mediante expresiones regulares), seleccionando una lista de documentos y devolviendo su complementario, son muy costosas en el motor de BD y se deben reducir al máximo, filtrando antes por clase y otros valores de campo.
3. El campo a la izquierda de la expresión,
puede ser "el campo _id al que hace referencia otro campo", por ejemplo: si
una clase de documentos unidad documental (udo) tiene una lista de
referencias a sus autores (autarql), se puede buscar:
· cla=udo autarql._id=autarq.N150
: las unidades documentales que
tengan en su lista de autores el de _id autarq.N150
· cla=udo autarql._id=(autarq.N150,autarq.N120,autarq.N122)
: lo mismo
buscando en un grupo de 3 autores
La correspondencia de la sintaxis simplificada de uso común, con el lenguaje de BD:
Sintaxis reducida Ingrid | Búsqueda mongoDB find() | Significado |
identificador | {find:{'_id':'identificador'}} | un único concepto |
cla==cod_superclase | {find:{"cla":{"$in":["cod_superclase", "cod_subclase1", "cod_subclase2" ,...]}} | concepto de una clase o cualquiera de sus subclases a
todos los niveles. No se soporta cla==["bin","car"] , es decir,
sobrecargar el = también para un conjunto de clases. |
campo! | {find:{'campo':{"$exists":false}}} | no existe el campo (no está puesto campo=null, sino que no se graba en BD) |
campo!! | {find:{'campo':{"$exists":true}}} | existe el campo |
limit=num | {find:{limit: num}} | devuelve sólo los primeros 'num' valores según el criterio de ordenación aplicado |
campoLista.size=entero | {find:{"campoLista":{"$size":entero}}} | Compara buscando por la longitud de un array o lista (como gral.size=4) |
campoLista.indice!! | find:{"campoLista.indice":{"$exists":true}} | Comprueba si existe en la lista el elemento indice. Por ejemplo gral.2!! lo que significa: ¿existen al menos 3 imágenes? (base 0) |
campo=valor | {find:{"campo": valor}} | concepto con valor (numérico o alfanumérico) en un campo. Por defecto, si sólo hay una condición se considera el campo _id y se puede omitir campo= |
campo>=valor | {find:{"campo":{"$gte":valor}}} | expresión de comparación. Otras correspondencias similares: > ($gt) >= ($gte) > ($lt) <= ($lte) != ($ne) |
'<usu>' | Macro que sustituye esos 5 caracteres por el código de usuario actualmente validado en BD. Útil para seleccionar y comparar con personas, grupos de trabajo etc. relacionados con el usu. | |
campo1=valor campo2<valor | {find:{"campo1": valor, "campo2":{"$lt": valor}}} | condición AND: el espacio en blanco entre dos campos indica que se cumpla la primera y la segunda |
campo1=valor | campo2<valor | {find:"$or":[{"campo1": valor},{"campo2":{"$lt": valor}}]} | condición OR: una barra vertical significa que se cumpla una O la otra |
campo=/expr_regular/ | {find:{campo:{"$regex":'expr_regular'}}} | valor de un campo coincidente con una expresión regular, como
una máscara: ^(inicio) $(final) .(cualquiera) *(0 ó más
caracteres) +(1 ó más caracteres) ?(0o1) [...](alguno)
[^...](ninguno). Se admiten todos los modificadores de expresión regular como por ejemplo /expr_regular/i que ignora mayúsculas/minúsculas, equivale a find:{campo:{"$regex":valor,"$options":"i"}}} Se ha implementado internamente también la expresión != (distinto) a la expresión regular |
campo=[listaValores] | {find:{"campo":{"$in":[valor1,valor2... ]}}} | búsqueda dentro de una lista de valores concretos. Si la expresión es != (distinto) sería excluido de la lista de valores ($nin) |
campo1=(tabla.campo2) | {find:{"campo": {"$in":[valor1,valor2, ... ]}}, sort:{"_id":1}} | con = cruce de referencias, devuelve los
documentos a los que se hace referencia en el campo indicado entre
paréntesis. Si la expresión es un signo != (distinto), la búsqueda sería NOT IN la lista de valores del campo, en color azul. NO SE PUEDEN especificar varias en la misma búsqueda. |
where="expr_operadores" | {find:{condición, "$where": "expr_operadores"}} | Expresión de filtro, como
una subconsulta pero sin cruzar identificadores, es decir, siempre operando
con campos de la misma clase. La expr_con_operadores es con sintaxis
javascript. Ejemplo: cla=gra where="obj.tam >= obj.oritam && obj.anc!" |
consulta<lista _id> => campo<lista _id> | mongo.distinct (campo,busqueda) | Subconsulta similar a un JOIN de SQL usando el operador => entre la consulta y uno de los campos de los conceptos devueltos. Proyecta una selección de _ids sobre otra devolviendo una 3ª lista de _ids coincidentes, con una sola aparición |
campo#tipo | {find:{"campo":{"$type": "tipo"}}} | buscar por tipo de campo javascript: 1-Double 2-String 3-Objeto 4-Array 5-BinayData 7-objectId 8-Boolean 9-Date 10-null 11-regularExpression 13-avaScript 16-Integer 17-timeStamp 18-long entero de 64 bits 19-decimal de 128... y otros obsoletos |
campo[+-] | {sort: {"campo":1}} | ordenación ascendente (+). Descendente con signo -, que se traduce en mongoDB con el valor -1) |
Ejemplo de búsquedas habituales
-
Todas las clases : /^\./ o {_id:/^\./}
- Tareas con incidencias ordenadas por clase y fecha de cierre : cla==tar numinc!! cla+ feccer-
- Tareas programadas fuera del mes jul-2016 : cla==tar fecpro>20160700 fecpro<20160800
- Correctivas pendientes de programación : cla=tarcor fecpro!
- Tareas preventivas abiertas, ordenadas por Fecha programada, espacio y de forma descendente por clase · código :
cla=tarpre feccer! fecpro+ esp+ _id-
- Conceptos de clase distrito o bin, orden comenzando por distritos: cla=["espdis","bin"] cla-
- Supongamos una clase de conceptos bin que tiene una lista de componentes cmpl (de clase
cmp)
La búsqueda de 'Componentes que tengan
bin' : (bin.cmpl._id)
La búsqueda 'Componentes SIN bin' :
cla=cmp
_id=(bin.cmpl._id!)
- Carpetas con más de 2 imágenes (hay que filtrar primero los que tienen
gral, sino dará error al comparar) : cla=car gral!! where="this.gral.length>2"
- Carpetas sin descendientes (ojo a la igualdad con dos ==) : cla=car desl!!
where="this.desl.length==0"
(Ingrid se ocupa de no guardar en
BD estos
objetos, pero un script podría guardar valores 'incorrectos' como esos)
Otro ejemplo más completo:
búsqueda: 'Tareas (de cualquier subclase), que tengan fecha programada y con fecha de cierre posterior al 1/1/2016'
sintaxis reducida de Ingrid: cla==tar fecpro!! feccer>20160001
sintaxis find() de mongoDB: {find:{"cla":{"$in":["tar","tarcor","tarpre"]},"fecpro":{"$exists":true},"feccer":{"$gt":20160001}}, sort:{"_id":1}}
Búsquedas más avanzadas (principalmente para administradores)
* Buscar una única repetición de proyectos, seleccionando de una tabla de
personas (per), y los proyectos de su tabla de relaciones (lista de precios, prel): cla==per => prel.pry
* Para el caso de programar operaciones: Buscar las zonas que son
apuntadas por elementos de inventario de distintas clases, filtrados por alguna condición
(siendo el campo 'tipo' común a todas las clases de bins):
(cla==SUP tipo=SI => ZG)
Las subclases de SUP (distintas superficies) tienen un campo
'tipo',
queremos seleccionar las superficies de tipo=SI y seleccionar sólo los _id
de la clase zona (ZON) apuntadas por el campo SUP.ZG. El paréntesis devuelve
los _id y aunque en general no es obligatorio, en este caso, sí __id=( ... )
* Complicando más está búsqueda, en una operación podemos necesitar hacer una selección como la anterior, pero además en más de una clase y LUEGO aplicar las medidas de las tareas a todos esos bins (los elementos de inventario) en vez de al bin principal de las tareas (las zonas):
* Para eliminar una gran lista de clases, como estos conceptos son
especiales y no se pueden eliminar seleccionando masivamente, en la pestaña
Menú > Base de datos > Búsquedas se pueden seleccionar con: cla='' cod!=['','O','A','car','usu','pro']
Indicando en la lista las clases que queremos mantener y pulsando
Elimina documentos...
* Imágenes con tamaño mayor o igual que original, aplicando con sintaxis
mongoDB un filtro WHERE:
{find:{cla:"gra","$where":"obj.tam >= obj.oritam && obj.anc!"}}
y la misma con sintaxis abreviada Ingrid:
cla=gra tam!! where="obj.tam >= obj.oritam && obj.anc!"
* Imágenes con las extensiones habituales (mediante una expresión regular):
cla==gra cod=/\.png$|\.jpg$|\.jpeg$/i
* Clases que contengan un campo concreto en su definición ('ico', por ejemplo)
úril para buscar campos antiguos u obsoletos, por ejemplo. Atención al espacio
en blanco después del primer = : cla= caml.cod=fec
* Imágenes con códigos con espacio en blanco: cla=gra cod=/.\s[.]pg/i
Uso en procedimientos javascript
El procedimiento más sencillo para devolver una lista de conceptos con una búsqueda concreta sería como:
bas.leeConceptos("cla=car res=Preventivas", cb);
Devuelve la lista de conceptos de clase carpeta con resumen exactamente igual a "Preventivas"
Si creamos dos parámetros con los códigos clase y resumen, para admitir un código de clase y una expresión con la que comparar el campo resumen de las carpetas, podríamos ponerla:
bas.leeConceptos("cla="+vals.clase+" res=/"+vals.resumen+"/i num-", cb);
Ambas devuelven una lista con los conceptos que cumplen el criterio de la búsqueda,
Otras formas de recuperar información
Otros 2 métodos para buscar información en la BD de forma más general son:
- Lista de conceptos de una clase. Nos da todos los elementos, que se pueden filtrar con los campos del formulario de búsqueda que tiene cada clase en la persiana Búsqueda. Son todos los campos de la clase que no estén restringidos por el administrador en los formularios de búsqueda.
- Lista de conceptos de una clase filtrados por el valor de un campo de tipo lista (clasificación). Haciendo clic en el icono de la línea de definición del campo, se muestra la lista de todos los posibles valores y haciendo clic en uno de los valores, se muestra la lista de conceptos asociados a ese,
Sintaxis de expresiones regulares
Las expresiones regulares que utilizaremos para búsquedas en mongoDB son las del estándar compatible con Perl.
La utilidad online https://util.ingra.es/regular sirve para probar diversas combinaciones sobre una cadena, y también diversas funciones que usan expresiones regulares (test, split, match, exec...)
Notas rápidas
Clases de caracteres
. un carácter cualquiera excepto /n
\w \d \s letra o dígito [A-Z a-z0 -9_], dígito [0-9], blanco [ \f\n\r\t\v]
\W \D \S NO letra, dígito, o espacio en blanco
[abc] cualquiera de los caracteres entre corchetes
[^abc] ninguno de los caracteres
[a-g] rango de caracteres entre a y g
Anclas
^abc$ comienzo de entrada o línea, final de entrada o línea
\b límite de palabra: espacio, retorno...
Caracteres de escape
\. \* \\ caracteres especiales de escape
\t \r \n tabulador, retorno y salto de línea
\\u00A9 carácter unicode © como código de escape
Grupos y Lookarround
(abc) patrón o grupo de selección, recuerda [0]..[n]
\1 retro-referencia a grupo #1
(?:abc) grupo de no selección
(?=abc) positive lookahead
(?!abc) negative lookahead
Cuantificadores y Alternancia
a* a+ a? 0 o más veces, 1 o más veces, 0 o 1
a{5} a{2,} exactamente n apariciones del carácter anterior, n o mas
a{1,3} como mínimo n y como máximo m apariciones del carácter anterior
a+? a{2,}? concordar los menos posibles
ab|cd concordar ab o cd
\num \n octal, \xn
Modificadores
Detrás de las contra-barras:
i Si se aplica este modificador, las letras en el patrón coincidirán tanto con letras mayúsculas como minúsculam Si se aplica este modificador, las letras en el patrón coincidirán tanto con letras mayúsculas como minúscula
S Si se aplica este modificador, un meta-carácter punto en el patrón coincide con todos los caracteres, incluyendo nuevas líneas. Sin él, las nuevas líneas son excluidas. Este modificador es equivalente al modificador /s de Perl. Una clase negativa como [^a] siempre coincidirá con un carácter de nueva línea, independientemente de la aplicación de este modificador.
x Si se aplica este modificador, los caracteres de información de espacios en blanco en el patrón se ignoran totalmente excepto cuando están escapados o dentro de una clase carácter, y los caracteres entre un # sin escapar fuera de una clase carácter y el siguiente carácter nueva línea, inclusive, también son ignorados. Esto es equivalente al modificador /x de Perl, y hace posible incluir comentarios dentro de patrones complicados. Observe, sin embargo, que esto se aplica sólo a caracteres de información. Los caracteres espacio en blanco nunca pueden aparecer dentro de secuencias de caracteres especiales en un patrón, por ejemplo dentro de la secuencia (?( la cual inicia un sub-patrón condicional.
AA Si se aplica este modificador, el patrón es forzado a ser "anclado", es decir, se le obliga a coincidir sólo con el inicio de la cadena que está siendo buscada (la "cadena objetivo"). Este efecto también se puede lograr mediante construcciones apropiadas en el patrón mismo, lo cual es la única manera de hacerlo en Perl.
D Si se aplica este modificador, un meta-carácter dólar en el patrón coincidirá sólo con el final de la cadena objetivo. Sin este modificador, un dólar coincide también inmediatamente antes del carácter final si éste es una nueva línea (pero no antes de cualquier otra nueva línea). Este modificador es ignorado si el modificadr m se aplica. No existe equivalente a este modificador en Perl.
S Cuando un patrón se va a usar varias veces, merece la pena dedicar más tiempo a analizarlo a fin de acelerar el tiempo tomado para las comparaciones. Si se aplica este modificador, se realiza este análisis extra. Actualmente, estudiar un patrón es útil sólamente para patrones no anclados que no tienen un carácter de inicio único fijo.
U
Este modificador invierte la "codicia" de los cuantificadores de modo que no
sean codiciosos por defecto, pero se vuelven codiciosos si son seguidos por ?.
Esto no es compatible con Perl. También se puede aplicar por un modificador
de ajuste dentro del patrón (?U)
o por un signo de interrogación detrás del cuantificador (p.ej. .*?).
Notas detalladas
Los patrones de las expresiones reguladores compatibles con Perl deben empezar y acabar con un delimitador, que normalmente es la barra (/). En caso de que la barra forme parte del patrón, se puede:
- escribir en el patrón la barra precedida de una contrabarra (\/)
- utilizar otro carácter, que no sea uno de los caracteres especiales, como delimitador (por ejemplo, !, -, etc.)
Los patrones de expresiones regulares compatibles con Perl admiten modificadores, que se incluyen en el patrón, después del limitador final.
Los siguientes patrones son comunes a POSIX extendido y a compatibles con Perl, con una diferencia muy importante que es que las clases de carácter que incluyen caracteres alfabéticos ([[:alnum:]], [[:alpha:]], etc.) en POSIX no incluyen vocales acentuadas, ñ, ç, etc, mientras que en PECR sí.
Patrón | Significado | |
---|---|---|
c | carácter c | |
. | cualquier carácter | |
^c | eempezar por el carácter c | |
c$ | terminar por el carácter c | |
c+ | 1 o más caracteres c | |
c* | 0 o más caracteres c | |
c? | 0 o 1 caracteres c | |
\n | nueva línea | |
\t | tabulador | |
\ | escape, para escribir delante de caracteres especiales: ^ . [ ] % ( ) | * ? { } \ | |
(cd) | caracteres c y d agrupados | |
c|d | carácter c o d | |
c{n} | n veces el carácter c | |
c{n,} | n o más caracteres c | |
c{n,m} | desde n hasta m caracteres c | |
[a-z] | cualquier letra minúscula | |
[A-Z] | cualquier letra mayúscula | |
[0-9] | cualquier dígito | |
[cde] | cualquiera de los caracteres c, d o e/ | |
[c-f] | cualquier letra entre c y f (es decir, c, d, e o f) | |
[^c] | que no esté el carácter c | |
[[[:alnum:]] | cualquier letra o dígito | |
[[:alpha:]] | cualquier letra | |
[[:digit:]] | cualquier dígito | |
[[:lower:]] | cualquier letra minúscula | |
[[:punct:]] | cualquier marca de puntuación | |
[[:space:]] | cualquier espacio en blanco | |
[[:upper:]] | cualquier letra mayúscula |
Los siguientes patrones son exclusivos de compatibles con Perl y no existen en POSIX extendido:
Patrón | Significado |
---|---|
[[:ascii:]] | caracteres con código ASCII de 0 a 127 |
[[:blank:]] | espacios o tabuladores |
[[:cntrl:]] | caracteres de control |
[[:graph:]] | caracteres de impresión, salvo el espacio |
[[:print:]] | caracteres de impresión, espacio incluido |
[[:word:]] |
cualquier letra o dígito y el guión bajo |
[[:xdigit:]] | cualquier dígito hexadecimal |
\w | cualquier letra o dígito y el guión bajo |
\W | cualquier cosa que no sea letra o dígito y el guión bajo |
\s | cualquier espacio en blanco |
\S | cualquier cosa que no sea un espacio en blanco |
\d | cualquier dígito |
\D | cualquier cosa que no sea un dígito |
\b | inicio o final de palabra |
\A | comienzo |
\Z | final (incluido salto de línea) |
\z | final |
Ejemplos de expresiones regulares
Patrón | Cadena | ¿Cumple? | Comentario |
---|---|---|---|
abc | awbwc | No | Los caracteres tienen que estar seguidos. |
34abc | Sí | No importa que hayan caracteres antes... | |
cbabcba | Sí | ... o después. | |
a2b | g1da2b3 | Sí | Las expresiones regulares detectan letras, números, ... |
áb | 3áb4 | Sí | ... incluso acentos, ... |
a\$b | 1a$b2 | Sí | ... salvo los caracteres ^ . [ $ ( ) | * + ? { \ € que deben llevar una contrabarra \ antes, además de \n (nueva línea) y \t (tabulador) |
[aeiou] | bic | Sí | Los corchetes definen los caracteres admitidos en una posición ... |
bcd | No | ||
[^aeiou] | bic | Sí | ... o no admitidos |
aei | No | ||
[p-t] | avr | Sí | Se pueden definir rangos de caracteres... |
av1 | No | ||
[B-D] | PMD | Sí | ... en minúsculas o mayúsculas ... |
AV1 | No | ||
[0-9] | b9d | Sí | ... o números |
bcd | No | ||
[[:alpha:]] | Cualquier carácter alfabético | ||
[[:digit:]] | Cualquier número | ||
[[:alnum:]] | Cualquier número o carácter alfabéticos | ||
[[:punct:]] | Cualquier carácter que no sean letras y números (menos el euro) | ||
[[:space:]] | Cualquier tipo de espacio en blanco | ||
[[:upper:]] | Cualquier mayúscula | ||
[[:lower:]] | Cualquier minúscula | ||
^ab | cab | No | Los caracteres tienen que estar al principio |
abc | Sí | No importa que hayan caracteres después | |
ab$ | abc | No | Los caracteres tienen que estar al final |
cab | Sí | No importa que haya caracteres antes | |
^ab$ | ab | Sí | Tiene que empezar y acabar por ab ... |
abab | No | .... y no puede haber nada antes o después | |
ab?c | abcde | Sí | El carácter b puede estar entre a y c... |
acde | Sí | ... o no estar entre a y c ... | |
adcde | No | ... pero no puede haber otro carácter | |
a.c | abc | Sí | El . representa cualquier carácter ... |
a c | Sí | ... incluso el espacio el blanco, ... | |
ac | No | pero no la ausencia del carácter | |
abdc | No | o varios caracteres. | |
ab+c | abcde | Sí | El carácter b puede estar una vez... |
abbbcde | Sí | ... o varias ... | |
acde | No | ... pero tiene que estar al menos una vez. | |
ab*c | abcde | Sí | El carácter b puede estar una vez... |
abbbcde | Sí | ... o varias ... | |
acde | Sí | ... o ninguna. | |
ab{3}c | abbbc | Sí | Las llaves indican el número exacto de repeticiones del carácter, ... |
abbbbc | No | ... no puede haber más ... | |
abbc | No | ... ni menos. | |
ab{2,4}c | abc | No | Se pueden definir rangos con límite inferior y superior |
abbc | Sí | ||
abbbc | Sí | ||
abbbbc | Sí | ||
abbbbbc | No | ||
ab{2,}c | abc | No | Se pueden definir rangos sin límite superior |
a(bc){2}d | abcbcd | Sí | Los paréntesis definen agrupaciones de caracteres. En este caso bc tiene que aparecer repetido |
a(bc)?d | abcd | Sí | Aquí bc puede estar ... |
ad | Sí | ... o no estar, ... | |
abd | No | ... pero no puede aparecer sólo la b, o sólo la c u otro carácter | |
^a(b|d)c$ | abc | Sí | Entre la a al principio y la c al final puede estar el carácter b... |
adc | Sí | ... o el carácter d, ... | |
abdc | No | ... pero no los dos, ... | |
ac | No | ... ni ninguno de ellos. | |
^(ab)|(dc)$ | abc | Sí | Está la pareja ab al principio ... |
adc | Sí | ... o dc ... | |
abdc | Sí | ... o las dos, ... | |
ac | No | ... pero no ninguna | |
^(ab)$|^(dc)$ | abc | No | Está la pareja ab, pero sobra la c ... |
adc | No | ... o está la pareja dc, pero sobra la a. | |
dc | Sí | Está una de las dos |
Documentación procedente de:
http://regexr.com/
http://upv.s3.amazonaws.com/GeoEuskadiDemo/documentacion/javascript-Cheat-Sheet.pdf
http://www.mclibre.org/consultar/php/lecciones/php_expresiones_regulares.html
http://www.php.net/manual/es/reference.pcre.pattern.modifiers.php