Ayuda con StringRegExp

Pregunta Sin Miedo no te cortes cualquier cosa para empezar - Autoit se comienza facilmente.Para Ordenes o Comandos sueltos. Ver nota como preguntar.
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con StringRegExp

Mensaje por Ximorro »

Bueno me alegro de que ya vayamos llegando a algo.
avechuche escribió: >.*? = Esto significa que esta parte >.* puede aparecer o no? Entiendo que el "." es cualquier caracter (incluyendo el espacio?), el "*" es para que repita el carater anterior, pero el "?" no se sobre que parte de esto >.* trabaja. Calculo que sera sobre ".*" ya que ">" es un caracter "mio" y no un "comodin".
Comprendo que te haya confundido el interrogante, que suele significar "creo o uno", es decir "opcional", pero cuando está siguiendo a un carácter comodín de repetición (* o +, y creo que también los repetidores de llaves) entonces hace al comodín "no avaricioso", como ya he comentado por arriba. Por defecto son avariciosos, toman todo lo que pueden, pero entonces el KB y todo lo de después sería consumido por el asterisco y eso no nos interesa.
Así que en este caso especial trabajo sobre el asterisco, y tiene el significado que comento.
Por cierto igual "comodín" es una mala elección por mi parte, me refería a comodines de repetición. Es cierto que el punto es un comodín porque equivale a cualquier carácter, pero sólo a uno. Yo me refería sólo a los de repetición, así que mejor los llamamos "caracteres de repetición".
avechuche escribió: (?:-v\d+) = Esta parte la entiendo perfectamente "-v\d+", pero esto "?:" mas o menos, significa que lo que esta despues que eso no lo tiene que capturar en una celda aparte del array?
Ultima cosa. To lo que esta entre parentesis es lo que pone en cada celda del array?
Sí, entre paréntesis pones grupos capturadores, que es lo que StringRegExp devuelve en los modos con matriz.
Lo que quieres capturar lo pones entre paréntesis (si no hay nada entre paréntesis captura todo).
El problema es que los paréntesis se usan para agrupar subexpresiones para otras cosas, por ejemplo para controlar la precedencia del OR "|" o para aplicarles caracteres de repetición, etc.
En este caso agrupábamos para hacerlo opcional con el "?", pero eso no queremos que sea un grupo capturable, y la sintaxis para hacer un grupo no capturable es poniendo "?:" después del paréntesis de apertura.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Hola que tal, bueno vengo con otra media duda, resulta que tengo lo siguiente

Código: Seleccionar todo

$String = "Muy lejano (1|323) D1
Lo que quiero es que "Muy lejano", "(1|323)" y "D1" queden en distintos nodos de un array, yo tengo lo siguiente

Código: Seleccionar todo

$Array = StringRegExp($String, "(\D+) \((\d+\|\d+)\) (D\d+)$", 1)
Explico por separado empezando de atras para adelante

"D1" = Puede ser cualquier letra (siempre 1 sola) seguida inmediatamente sin espacios de un numero que puede ser de 1, 2, 3 o 4 caracteres. Eso esta al final de la cadena, SIEMPRE, por eso el $ (¿Está bien asi?)
"\((\d+\|\d+)\)" = Capturo los datos que estan dentro de los parentesis. Siempre se cumple que es del tipo "numero|numero" y esta antes de "D1" con un espacio entremedio.
(\D+) = Aca esta la duda, puede ser cualquier cosa, puede haber letras, simbolos, parentesis, corchetes, cualquier cosa menos empezar con un espacio, lo unico q se es que esta al principio de la cadena y anterior a "\((\d+\|\d+)\)" con un espacio entre medio.

Por ejemplo:

Código: Seleccionar todo

$String = ".[12](dge) jdhwh 121223Muy lejano,vheh.dhjey (1|323) D1
Necesito

Código: Seleccionar todo

$String[0] = ".[12](dge) jdhwh 121223Muy lejano,vheh.dhjey"
$String[1] = "(1|323)"
$String[2] = "D1"
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con StringRegExp

Mensaje por Ximorro »

¿Cuál es la duda? ¿no funciona?
Ah, en el segundo ejemplo no funciona...
Vale a ver, ya que has empezado desde el final yo también ;-)

Efectivamente el $ ancla la ER al final.

Fíjate que D\d+ pone una "D" a piñón fijo. Si es una letra puedes poner \w. El \d+ está bien, pero que sepas que si quieres especificar que sea de 1 a 4 dígitos lo puedes poner con \d{1,4}. Así eso quedaría:
\w\d{1,4}

La parte del medio la veo perfecta ¡qué follón con los escapes! ¿eh? ;-)

La parte inicial... has puesto que coja cualquier cosa que no es un dígito, que no es lo que quieres, por eso no va la expresión.
Quieres que no empiece por espacio, pero después puede haber cualquier cosa.
En principio podemos probar esto: ^([^ ].*)
^: Al principio
[^ ]: No es un espacio (ahí dentro hay un espacio)
.*: y después cualquier cosa

Si no se te ocurren otros problemas esto en principio funciona con lo que has puesto, y no te dejará poner espacios al principio. Además te deja poner cosas como el segundo grupo y no se confunde:
$ER = "^([^ ].*) \((\d+\|\d+)\) (\w\d{1,4})$"
$String = "Alguna cosa (1|323) otra cosa (1|323) H3345"

dará:
[0] = Alguna cosa (1|323) otra cosa
[1] = 1|323
[2] = H3345


PROBLEMA: La librería PCRE que usa AutoIT para ER soporta Unicode, y en principio la librería está compilada con ese soporte ¡pero no funciona!. Me temo que internamente AutoIt hace algunas cosas con las cadenas que lo anulan, creo que es por el paso de parámetros. Así que cosas como \w significan "cualquier carácter que sea una letra... ¡¡del ASCII básico!!". Que va bien para los ingleses, vaya, pero no se consideran letras otros caracteres que para nosotros sí lo son, como vocales acentuadas y la ñ. Snif snif.
Así que si esa letra del final seguida de un número puede ser una Ñ o tener acentos hay que especificarlos uno a uno en un conjunto...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Muchas gracias Ximo, tuve ese problema con el \w, y no sabia porque era, ahora me di cuenta q esta hecho para los ingleses no mas ^^
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Vengo con otra inquietud.

Tengo lo siguiente
$Cadena = " texto aqui .123.123.123.3"
$aCadena = StringRegExp($Cadena, "([^ ].*) \.(\d+)\.(\d+)\.(\d+)\.(\d+)", 3)

Hago eso para obtener el texto y los numeros en diferentes celdas del array.
Mi pregunta es si puedo reemplazar "\.(\d+)\.(\d+)\.(\d+)\.(\d+)" por algo mas corto, ya que se repite 4 veces. Asi anda, pero para saber si hay alguna forma de repetir un grupo completo.
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con StringRegExp

Mensaje por Ximorro »

Si quieres capturar los grupos independientes me temo que no hay más remedio que hacerlo así, al menos de una sólo pasada.
Por poder agruparse se puede para comprobar el match, pero no para tomar todos los grupos, por ejemplo si siempre son 4 repeticiones:
([^ ].*) (?:\.(\d+)){4}
Pero de esta manera al hacer backtracking se borran las referencias a los grupos que va encontrando, al acabar el análisis sólo queda la última...

Si siempre son 4 grupos afortunadamente lo puedes hacer como has hecho, si fuera un número variable es cuando hay un problema. Yo lo intenté en mi programa que leía números, para que me los partiera en grupos de 3 y de 6, y efectivamente me decía que era un número bien formado, pero sólo me devolvía el último grupo así que no me sirvió para lo que quería. :-(
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Hola gente vengo con otra duda. Resulta que quiero tomar todos los archivos con extension que no sean ".exe", tengo este code, pero no se como ponerle q tome todo menos los exe.

$codeStringRegExpHotfix = '">([^<].*?(?:\.[a-zA-Z]+))</a>'

Con ese code tomo todo los archivos, pero yo quiero que no me tome los ".exe" o cualquiera, sean 1 2 o 3 extensiones. Gracias!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con StringRegExp

Mensaje por Ximorro »

Mira, para ir rápido no voy a usar lo que tienes porque tendría que analizarlo y eso lleva tiempo ;-), te contesto a la consulta concreta.

Para hacer lo de una cadena que NO vaya seguida con otra se hace con lo que llaman una "lookahed assertion", que se especifica (la negativa) con (?!)
Así por ejemplo la ER
archivo\.(?!exe)
emparejará con los archivos que se llamen "archivo" y NO tengan extensión "exe"

Para poner varios pues pones el OR en la aserción, por ejemplo
archivo\.(?!(exe|bat))
emparejará con "archivo.com" pero no con "archivo.exe" ni "archivo.bat"

Con eso creo que ya puedes hacer lo que quieres. Por supuesto dependiendo de la entrada tendrás que tener en cuenta las mayúsculas o el fin de cadena.
Lo del fin de cadena es que no aceptará "archivo.exe" pero tampoco "archivo.exec". Si tiene que aceptar esto último tendrás que poner el fin de cadena (o los separadores correspondientes) dentro de la aserción, por ejemplo
archivo\.(?!exe$)
Esto ya acepta "archivo.exec" o "archivo.executable" pero no "archivo.exe"

Byeee
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Gracias Ximo pero no me va :S. Hago lo siguiente

$codeStringRegExpHotfix = '">([^<].*?\.[0-9a-zA-Z]+)</a>'

Lo que hace esa ER es captar el dato que está entre ">" y "</a>", siempre y cuando el primer caracter que capture no sea "<", osea desp del ">" no puede haber un "<". Captura el nombre del archivo y su extension. Lo que ahora quiero es que no me capture los que son ".exe", pero nada no me lista ningun archivo :(

EDITO:

Ya probe con varias convinaciones pero nada :S

$codeStringRegExpHotfix = '">([^<].*?\.(?!exe))</a>'
$codeStringRegExpHotfix = '">([^<].*?\.?!exe)</a>'
$codeStringRegExpHotfix = '">([^<].*?\.!exe)</a>'

Y nada :S
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Ayuda con StringRegExp

Mensaje por Ximorro »

Vale, se me olvidó decir una cosa que es importante si la ER tiene que seguir mirando cosas después de la aserción: para comprobar la aserción NO SE CONSUMEN CARACTERES.
El nombre era más importante de lo que parece, lookahead o lookbehind assertions significa "comprobaciones mirando hacia adelante o hacia atrás". "Mirar" significa que la ER se espera donde está y mira sin consumir para el matching. Mejor con un ejemplo:

Eso quiere decir que por ejemplo si tienes la ER
<archivo\.(?!exe)>

e intentas comprobar el texto <archivo.txt>, que debería cuadrar según lo que queremos, lo que ocurre es lo siguiente:
.- Empieza con los literales "<archivo" y el punto, que es literal porque está escapado. No problem, por ahora lo encuentra todo.

.- Ahora se encuentra con la aserción "mira por delante" (lookahead assertion) que le dice que lo que sigue NO DEBE SER la cadena "exe". Para ello mira los 3 siguientes caracteres, pues la aserción es de 3 caracteres, y se encuentra con "txt", que efectivamente no coincide con "exe", con lo que se cumple lo que queremos (en realidad sólo mira el primer carácter porque la primera "t" de "txt" ya no coincide con la primera "e" de "exe", pero bueno).

.- Lo importante es que el "puntero analizador" no se ha movido, y ahora cuando sigue comprobando la cadena NO HA CONSUMIDO "txt". Esto quiere decir que después de comprobar la aserción el siguiente carácter de la ER es ">", pero al mirar en la cadena para ver si coincide se encuentra con la primera "t" de "txt", y como no es igual al ">" la ER no hace match con la cadena.

Repito: esto ocurre porque cuando sigue mirando la cadena después de comprobar la aserción, los caracteres mirados en la aserción son ignorados, así que luego sigue comprobando a partir de ellos.

¿Cómo se soluciona? No basta con decirle que "no sea 'exe' ", si quieres que siga mirando tienes que hacer matching con la extensión que haya. Como ejemplo simplificado supongamos que la extensión son siempre 3 caracteres alfabéticos. Entonces la ER de arriba la arreglaríamos así:
<archivo\.(?!exe)\w{3}>

De esta manera (?!exe) mirará que efectivamente no está la cadena "exe" después de "<archivo.", pero el "puntero analizador" aún está en el punto, con lo que lo siguiente que hace es cuadrar "txt" con \w{3}, lo que funciona pues son 3 caracteres alfabéticos, finalmente se encuentra con el literal ">" con lo que la cadena hace match con la ER. "txt" se ha consumido con \w{3}, no con la aserción, porque la aserción no consume los caracteres aunque los haya mirado.

Naturalmente ese \w{3} tendrás que cambiarlo con la ER que case con las extensiones permitidas, esto era simplificado para que se vea mejor el asunto de la aserción. Fíjate que \w{3} acepta "exe", pero eso no es problema porque la aserción se comprueba antes, para eso es.

Así que tu ER en principio sería:
>([^<].*?\.(?!exe)\w{3})</a>

Y sí, los paréntesis de la aserción (?!cadena) son obligatorios, y no es un grupo capturable.

Byeee
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Ayuda con StringRegExp

Mensaje por Chefito »

Muy buena la explicación de Ximorro.

Solo he escrito este post para recordar a los usuarios que si ponéis un ejemplo del texto a tratar, nos va a resultar mucho más fácil resolver las dudas que tengáis, ya que podríamos trabajar sobre ese ejemplo e ir probando cosas. Si no ponéis ejemplos, a muchos nos entra perrería y ni si quiera lo intentamos (por ejemplo yo :smt005 ).
Ya ha habido casos, y recuerdo uno en que Ximorro estuvo implicado, en el que por no ponernos bien el texto o no explicarnos bien las cosas, se dieron muchas soluciones que no era lo que pedía el usuario.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
BasicOs
Site Admin
Mensajes: 2083
Registrado: 21 Nov 2006, 19:24
Ubicación: El Internet - (Canarias, España)
Contactar:

Re: Ayuda con StringRegExp

Mensaje por BasicOs »

Buen tema esta profundizando banstante. Ahora lo puse como fijo ;) Salu22:) :smt023 :smt023
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Muchas gracias Ximo, anda perfecto, estuve buscando ejemplos, y todos tenias el \w pero no sabia que funcion cumplia. Ahora ya lo se. Gracias de nuevo y buenisimo que lo hallan puesto de stiky, muy buen post con exelentes explicaciones.
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Bueno vengo con una duda pequeña, resulta que tengo un archivo de texto y quiero meter en un array mediante ER cada linea y lo hago de la siguiente manera StringRegExp(FileRead($sFile), ".+", 3). Hasta ahi todo mas que bien, pero con esa forma, cada resultado al final mantiene el salto de linea y yo lo necesito sin el salto de linea.
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Me auto respondo. Lo hice asi ... $aDirectorios = StringRegExp(FileRead($sFile), "\V+", 3) toma cada linea del archivo de texto pero sin el salto de linea del final.
Última edición por avechuche el 31 Mar 2013, 00:26, editado 1 vez en total.
avechuche
Hacker del Foro
Mensajes: 188
Registrado: 13 Ago 2009, 09:53

Re: Ayuda con StringRegExp

Mensaje por avechuche »

Hola gente vengo con una duda:

Esta expresion regular

Código: Seleccionar todo

(?i)\A(?!x86|Server)$
Es lo mismo que esta?

Código: Seleccionar todo

(?i)\A(?!x86$|Server$)
Otra cosa, que significa el "?!", no puedo encontrar por ningun lado el significado ...

Y que diferencia hay en usar el simbolo "^" para empezar una cadena, que la combinacion "\A"? Lo mismo para el final de una cadena. Gracias!
Responder