Hilo oficial: Solicitudes de Expresiones Regulares

Iniciado por WHK, 8 Mayo 2015, 21:53 PM

0 Miembros y 1 Visitante están viendo este tema.

WHK

Obtener el contenido entre etiquetas XHTML:

Código
<div id="demo">Contenido</div>

Expresión
/<div\sid="demo">(.+?)<\/div>/si

Resultado:
Contenido

Eleкtro

#11
Pues aquí va una expresión regular para capturar una Ipv6:
Código (vbnet) [Seleccionar]
        ''' ----------------------------------------------------------------------------------------------------
        ''' <summary>
        ''' A pattern that matches an IPv6 address.
        '''
        ''' For Example:
        ''' FE80:0000:0000:0000:0202:B3FF:FE1E:8329
        ''' </summary>
        ''' ----------------------------------------------------------------------------------------------------
        Public Const Ipv6 As String =
            "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"


o una Ipv4, cómo expresión alternativa a la que ha publicado WHK:
Código (vbnet) [Seleccionar]
        ''' ----------------------------------------------------------------------------------------------------
        ''' <summary>
        ''' A pattern that matches an IPv4 address.
        '''
        ''' For Example:
        ''' 127.0.0.1
        ''' </summary>
        ''' ----------------------------------------------------------------------------------------------------
        Public Const Ipv4 As String =
            "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"


PD: Sintaxis VB.Net

Saludos








WHK

#12
Está bueno agrupar en 3 el grupo de la red a diferencia de la de owasp que las hace por separado, pero de todas maneras deberías agregarle el comienzo ^ y el final $ o si no cuando uses esa validación en un campo de texto que solo soporte un valor de ip validará texto basura antes y después de la ip como por ejemplo:

127.0.0.1' union select '1

Dando paso a una inyección SQL :P

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' A pattern that matches an IPv4 address.
'''
''' For Example:
''' 127.0.0.1
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Const Ipv4 As String = "^((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])$"


En ese caso a tu clase deberías agregarle una opción booleana que indique si debe realizar una validación exacta o parcial, o sea con todo el contenido o parte de el en el caso que quieras validar ya que en tu código solo estás buscando una ip y no validando.

WHK

Validación de URL:

^((mailto\:|(news|(ht|f)tp(s?))\:\/\/){1}\S+)$

Ejemplos:
http://www.google.cl/
ftp://www.google.cl/
mailto:demo@google.com


Eleкtro

#15
Tengo una expresión regular que me está volviendo loco, la utilizo en Pascalscript en combinación con otras expresiones, y ya no se cómo tratar de mejorar más este RegEx, no hace lo que yo quiero en ciertas circunstancias.

¡A ver si alguien me puede echar una mano!.

La expresión:
\A([^\-]*?)\s*\-\s*(.*?)\s*([\(\[])?((ft[\.\s]|feat[\.\s]|featuring[\.\s])[^\(\)\{\}\[\]]*)([\)\]])?(.+)?\Z

Reemplazamiento por:
$1 $4 - $2$7

Nombres de archivo de prueba:

  • kill the noise - all in my head feat. awolnation (batou mix)
  • artist - track name feat. Mister 漢字仮----名交じり文 [usa remix]
  • kill th-e noise - all in my head (feat awolnation)

La supuesta finalidad de esta expresión que diseñé, cómo ya habreis supuesto, debería servir para extraer la parte "feat..." del nombre del archivo, y colocarlo al principio del string junto al nombre del artista.

Por ejemplo:

De:
kill the noise - all in my head feat. awolnation (batou mix)
A:
kill the noise feat. awolnation - all in my head (batou mix)


De:
artist - track name feat. Mister 漢字仮--名交じり文 [usa remix]
A:
artist feat. Mister 漢字仮--名交じり文 - track name [usa remix]


La expresión funciona bien, excepto cuando en el nombre del archivo existe algún guión de más antes del string "feat..."

Por ejemplo, esto:
kill th-e noise - all in my head (feat awolnation)
Me lo reemplaza por esto otro:
Kill Th Feat. Awolnation-E Noise - All In My Head
Cuando realmente debería reemplazarlo así:
Kill Th-E Noise Feat. Awolnation - All In My Head


Los nombres de los archivos se puede desglosar así:
NOMBRE_ARTISTA - NOMBRE_CANCION FEATURING_ARTISTA (POSIBLE_TEXTO_EN_PARENTESIS)


Me está siendo muy complicado idear la lógica, ya que "NOMBRE_ARTISTA" puede contener un nombre con uno o varios guiones, al igual que "NOMBRE_CANCION", "FEATURING_ARTISTA" o "POSIBLE_TEXTO_EN_PARENTESIS" pueden tener nombres con guión, por ejemplo:
Dj E-nergy C-21 - My Super-hero track! (feat Dj Ass-hole)

Eso ya es dificil ...he?.

Lo realmente complicado es que "NOMBRE_ARTISTA" - "NOMBRE_CANCION" se separa por otro guión, y entonces no se cuando parar de capturar.

¿A alguien se le ocurre algo?, no importa que la expresión sea perfecta ...creo que no existe el modo de que sea perfecta debido a los guiones (imposible predecir cuando hay que separar  "NOMBRE_ARTISTA" de "NOMBRE_CANCION"), pero si que busco ayuda para mejorar lo que tengo, que no trabaja del todo bien.

Puedo aplicar varias expresiones distintas para ir formateando el string  que as´uedcnado para usar una e siguiente RegEx ...si eso ayuda, ya que en una sola expresión dudo que pueda hacerlo todo bien.

Saludos!








explorer

#16
Hola. He encontrado una solución, pero como no conozco Pascalscript, yo he usado Perl v5.18:
#!/usr/bin/perl
use v5.18; # garantizamos un buen soporte de Unicode
use utf8::all; # activamos todo el soporte para UTF-8
use re '/xu'; # las exp. reg. tendrán estas opciones, por defecto

my @tests =
( 'kill the noise - all in my head feat. awolnation (batou mix)'
, 'artist - track name feat. Mister 漢字仮--名交じり文 [usa remix]'
, 'kill th-e noise - all in my head (feat awolnation)'
, 'Dj E-nergy C-21 - My Super-hero track! featuring Dj Ass-hole (usa remix)'
, 'Dj E-nergy C-21 - My Super-hero track! (feat Dj Ass-hole)'
);

my $del1 = qr/[([]/;
my $del2 = qr/[])]/;
my $featuring = qr/
   (?<d1>$del1)?
   (?<featuring>feat(?:uring|[.]|) \s .+?)
   (?(<d1>)$del2)
/;
my $artista = qr/(?<artista>.+?)/;
my $resto = qr/
   (?<cancion>.+?) \s+
   (?:$featuring \s*)?
   (?<extra>$del1 .+? $del2)?
   $
/;
my $titulo = qr/^ $artista \s+ - \s+ $resto $/;


for my $test (@tests) {

   $test =~ /$titulo/;

   say $test;
   say join " ", @+{qw(artista featuring)}, '-', @+{qw(cancion extra)};
   say '-' x 30;
}

Lo que sale es:
kill the noise - all in my head feat. awolnation (batou mix)
kill the noise feat. awolnation - all in my head (batou mix)
------------------------------
artist - track name feat. Mister 漢字仮--名交じり文 [usa remix]
artist feat. Mister 漢字仮--名交じり文 - track name [usa remix]
------------------------------
kill th-e noise - all in my head (feat awolnation)
kill th-e noise feat awolnation - all in my head
------------------------------
Dj E-nergy C-21 - My Super-hero track! featuring Dj Ass-hole (usa remix)
Dj E-nergy C-21 featuring Dj Ass-hole - My Super-hero track! (usa remix)
------------------------------
Dj E-nergy C-21 - My Super-hero track! (feat Dj Ass-hole)
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
------------------------------

Eleкtro

#17
Cita de: explorer en 27 Septiembre 2015, 20:46 PM
(Los códigos que aparecen &#28450; y demás, no son del código original, sino los caracteres originales del título de la canción. Si no se ven, es por limitaciones de este foro, que no representa esos caracteres).

Es un bug que llevo años reportando de vez en cuando, pero nadie me hace caso. Una solución temporal es que uses la etiqueta CODE, tal cual, sin especificar un valor de GeShi.




Cita de: explorer en 27 Septiembre 2015, 20:46 PMHola. He encontrado una solución, pero como no conozco Pascalscript, yo he usado Perl v5.18:

Te agradezco muchísimo la ayuda prestada!!, pero desgraciadamente una solución en Perl no me serviría, si yo pudiese utilizar un script en el lenguaje que sea para resolver el problema entonces si, pero no es posible por que utilizo el programa para aplicar muchos filtros, transiciones de caracteres, RegEx y demás (en total más de 70 cosas), trasladar toda la lógica a otro lenguaje sería complejo y para mi supondría desarrollar una GUI también xD.

El programa está desarrollado en Delphi (imagino que usará el motor RegEx de Delphi/Object-Pascal), con soporte adicional para usar scripts en pascal-script.




En StackOverflow formulé esta misma pregunta, aquí pueden encontrar más detalles:
http://stackoverflow.com/questions/32807698/regex-pattern-to-limit-dashes-in-these-circumstances

Desglosemos imaginariamente los nombres de archivo de esta manera:
[0]ARTIST   [1]DASH   [2]TRACK   [3]FEAT_ARTIST   [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}

Pues verás, yo llegué a la conclusión de que es imposible que exista una lógica para determinar cuando se debe separar (0)ARTIST de (2)TRACK, ya que ambos pueden contener varios guiones (Dj E-Nergy C-21 - Nombre-de-cancion feat loquesea), yo llegué a esa conclusión así que lo que intenté fue hacer algo mucho más realista, una exclusión, es decir, si (0)ARTIST o (2)TRACK contienen 1 guión, no modificar el string, limitar los guiones a uno algo cómo esto (\-){1} pero me has desarmado completamente al igual que el usuario que me respondió en StackOverflow mostrándome otra solución en Perl, ya no se si la conclusión a la que llegué fue inequivoca o no.

Cita de: explorerDj E-nergy C-21 - My Super-hero track! featuring Dj Ass-hole (usa remix)
Dj E-nergy C-21 featuring Dj Ass-hole - My Super-hero track! (usa remix)

Por ese motivo no entiendo en absoluto cual es la lógica que hay detrás para lograr separar correctamente los tokens del nombre del archivo cuando contienen varios guiones, ya que si no eres un humano no se puede saber lo que pertenece a un nombre y lo que no, ¿podrías explicármelo como lo conseguiste?, ¿supuestamente funcionará a pesar de la cantidad de guiones que pueda haber, sin margen de error?, para mi eso es mágia, no lo entiendo.

EDITO: Ah claro, ya lo entiendo, se busca un guión separado por espacios " - ", por eso sabes cuando partir, pero entonces eso no me sirve ya que el nombre del artista o el nombre de la canción también pueden contener un guión con espacios.

¡Ya decía yo que era imposible!. Entonces lo que realmente necesito es excluir los nombres, limitar la funcionalidad del Regex cuando solo exista un guión con espacios " - ", si se encuentran más guiones con espacios antes de la parte "...feat artists" entonces no modificar nada.

De todas formas, analizaré las partes de tu regex a ver si las puedo combinar en el orden en el que usas el join, a ver si de casualidad me funciona en el programa, pero yo creo que no me va a aceptar la sintaxis de (?:...).

Un saludo!








explorer

#18
La sintaxis (?:...) se refiere a que esos paréntesis solo van a agrupar expresiones, no queremos que capturen nada.

El motor RegEx está creada alrededor de la biblioteca PCRE (Perl Compatible Regular Expressions), así que la traducción debería ser fácil (bueno, es cierto que estoy usando "features" de los últimos Perl, así que es normal que la traducción sea complicada. En Stackoverflow te dan expresiones regulares más normales).

Cita de: Eleкtro en 28 Septiembre 2015, 13:20 PMEDITO: ¡Ah, claro, ya lo entiendo! Se busca un guión separado por espacios " - ", por eso sabes cuando partir, pero entonces eso no me sirve ya que el nombre del artista o el nombre de la canción también pueden contener un guión con espacios.
Sí, pero en los ejemplos mostrados no hay ningún nombre de artista que tenga un guión con espacios, así que se supone que esa es el "ancla" que podemos usar para hacer la partición. Y como se parte por la primera aparición de esa estructura, no importa que aparezca después en el nombre de la canción.

Voy a ver si puedo simplificarla un poco para que la puedas meter en el Delphi, pero creo que es casi idéntica a la que te dan en StackOverflow.

explorer

He mejorado un poco la exp. reg., y he añadido todos los ejemplos que pusiste en StackOverflow:

#!/usr/bin/env perl
use v5.18; # garantizamos un buen soporte de Unicode
use utf8::all; # activamos todo el soporte para UTF-8
use re '/xiu'; # las exp. reg. tendrán por defecto estas opciones

my @tests =
( 'kill the noise - all in my head feat. awolnation (batou mix)'
, 'artist - track name feat. Mister 漢字仮--名交じり文 [usa remix]'
, 'kill th-e noise - all in my head (feat awolnation)'
, 'Dj E-nergy C-21 - My Super-hero track! featuring Dj Ass-hole (usa remix)'
, 'Dj E-nergy C-21 - My Super-hero track! (feat Dj Ass-hole)'
, 'Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole'
, 'Dj E-nergy C-21 - My Super-hero track!'
, 'Carbin & Sirmark - Sorry Feat. Sevener'
, 'Flight Facilities - Heart Attack Feat. Owl Eyes (Snakehips Remix)'
, 'Flight Facilities - Heart Attack Feat. Owl Eyes [Snake--hips Remix]'
, 'Fedde Le Grand - Cinematic'
, 'Fedde Le Grand Feat. Denny White - Cinematic'
, 'Artist-Name - Track Name feat someone'
, 'Artist Name - Track-Name feat someone'
);

my $del1 = qr/[([]/;
my $del2 = qr/[])]/;
my $featuring = qr/
    (?<d1>$del1)?
    (?<featuring>feat(?:uring|[.]|) \s .+?)
    (?(<d1>)$del2)
/;
my $artista = qr/(?<artista>.+?)/;
my $resto = qr/
    (?<cancion>.+?) \s*
    (?:$featuring)? \s*
    (?<extra>$del1 .+? $del2)?
/;
my $titulo = qr/^ $artista \s+ - \s+ $resto \s* $/;


for my $test (@tests) {

    $test =~ /$titulo/;

    say $test;
    print $+{'artista'};
    for my $text (qw(featuring - cancion extra)) {
        if ($text eq '-') {
            print " -";
        }
        elsif ($+{$text}) {
            print " " . $+{$text};
        }
    }
    print "\n";
#    say join " ", @+{qw(artista featuring)}, '-', @+{qw(cancion extra)};
    say '-' x 30;
}

say $titulo;

El resultado es el esperado:

kill the noise - all in my head feat. awolnation (batou mix)
kill the noise feat. awolnation - all in my head (batou mix)
------------------------------
artist - track name feat. Mister 漢字仮--名交じり文 [usa remix]
artist feat. Mister 漢字仮--名交じり文 - track name [usa remix]
------------------------------
kill th-e noise - all in my head (feat awolnation)
kill th-e noise feat awolnation - all in my head
------------------------------
Dj E-nergy C-21 - My Super-hero track! featuring Dj Ass-hole (usa remix)
Dj E-nergy C-21 featuring Dj Ass-hole - My Super-hero track! (usa remix)
------------------------------
Dj E-nergy C-21 - My Super-hero track! (feat Dj Ass-hole)
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
------------------------------
Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
------------------------------
Dj E-nergy C-21 - My Super-hero track!
Dj E-nergy C-21 - My Super-hero track!
------------------------------
Carbin & Sirmark - Sorry Feat. Sevener
Carbin & Sirmark Feat. Sevener - Sorry
------------------------------
Flight Facilities - Heart Attack Feat. Owl Eyes (Snakehips Remix)
Flight Facilities Feat. Owl Eyes - Heart Attack (Snakehips Remix)
------------------------------
Flight Facilities - Heart Attack Feat. Owl Eyes [Snake--hips Remix]
Flight Facilities Feat. Owl Eyes - Heart Attack [Snake--hips Remix]
------------------------------
Fedde Le Grand - Cinematic
Fedde Le Grand - Cinematic
------------------------------
Fedde Le Grand Feat. Denny White - Cinematic
Fedde Le Grand Feat. Denny White - Cinematic
------------------------------
Artist-Name - Track Name feat someone
Artist-Name feat someone - Track Name
------------------------------
Artist Name - Track-Name feat someone
Artist Name feat someone - Track-Name
------------------------------
(?^uix:^ (?^uix:(?<artista>.+?)) \s+ - \s+ (?^uix:
    (?<cancion>.+?) \s*
    (?:(?^uix:
    (?<d1>(?^uix:[([]))?
    (?<featuring>feat(?:uring|[.]|) \s .+?)
    (?(<d1>)(?^uix:[])]))
))? \s*
    (?<extra>(?^uix:[([]) .+? (?^uix:[])]))?
) \s* $)

El último say muestra la exp. reg. completa, que es lo que sale al final de la ejecución.

He visto que la biblioteca PCRE2 sí que tiene soporte para capturas con nombres, que se hace casi indispensable en este caso. No sé si el control Regex de Delphi soporta la PCRE2 o si aún sigue con la PCRE.