• Publicidad

Orden de salida con Expresiones Regulares

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Orden de salida con Expresiones Regulares

Notapor Katty » 2006-09-01 19:37 @859

Hola a todos:

La verdad es que he aprendido mucho de perl con uds... sin embargo tengo el siguiente problema:

Necesito separar unos patrones en diferentes palabras, las cuales se encuentran escritas en una misma línea. Gracias a su ayuda puedo descomponer las palabras en los patrones, sin embargo necesito que aparezcan en el orden que vienen en la entrada. Ademas, las palabras que no sigan un patron deben imprimirse en la salida tal cual.

El problema es que no puedo generar la salida como deberia...

Por el momento tengo el siguiente codigo:


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
@patrones =                             # patrones a buscar
(       'ACRO?(?!(MA|SIS))',
        'ADENO?(?!(MA|SIS))',
        'OSIS',
        'OMA',
        'ITIS'

)

$sw = 1;
@lineas = <>;                            # lineas desde un archivo de entrada

foreach $palabra(@lineas)
        {my @encontrado;
        #busca patron en palabras de entrada
        foreach $patron ( @patrones )
                {if ( $palabra =~ /($patron)/i )        
                        {push @encontrado, $1;
                        $sw = 0;
                        }
                }
        #trata las palabras de entrada que no tienen patron
        if ( $sw == 1 )
           {push @encontrado, $palabra;
           $sw = 1;
           }
        @registro = join(" ", @encontrado);
        print @registro;
        print "\n";
        }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Probando el codigo se genera:

Entrada:

Chao
adenoma
acroma HOLA adenitis


Salida generada:

Chao

aden oma
acr aden oma itis


Salida deseada:

Chao
aden oma
acr oma HOLA aden itis


Como se pueden dar cuenta, despues de una palabra que no tiene patron, se imprime un espacio en blanco que no se me ocurre como eliminar...

Por favor, agradeceria su ayuda...

De antemano, muchas gracias!!! :lol:
Katty
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2006-08-30 17:11 @757

Publicidad

Notapor explorer » 2006-09-04 12:40 @570

Si no te separa 'HIPERHEPATO' es porque no le pusiste estos patrones:

'^HIPER'
'HEPATO?(?!(MA|SIS))'

El '^PER' no le afecta. O usas '^PER' o usas '(?<!HI)PER'.

Y para el caso de 'HEPATOMA', sólo necesitas asegurarte que existe el patrón 'OMA|OSIS' hacia el final.

Con los patrones que hay en el mensaje anterior a mí si que me funcionan y sí me separan las palabras.

El patrón correcto es 'HEPAT(O|ICAS)?(?!(MA|SIS))'.

Fíjate en la posición de los primeros paréntesis.

Este es mejor: 'HEPAT(O(?!(MA|SIS))|IC(O|A)S?)?', ya que tiene en cuenta el plural y masculino y femenino de HEPATICO.
Última edición por explorer el 2006-09-04 13:03 @586, editado 1 vez en total
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Dudas con una expresion

Notapor Katty » 2006-09-05 14:22 @640

Hola:

Tengo la siguiente duda con la expresion '(?<!(ABDO|SE|HE))MI(?<!ELO?(?!(MA|SIS))O?(?!(MA|SIS)))'

La idea es que reconozca el patron MI o MIO, pero que no se confunda con los otros patrones ABDOMIN o ABDOMINO, MIEL o MIELO, HEM o HEMI, MICR o MICRO ni SEMI.

Segun creo, la expresion anterior reune todos los patrones antes mencionados, pero perl me envia el siguiente error:

Variable length lookbehind not implemented before HERE mark in regex....


Lo mismo sucede con la expresion: '(?<!(E?ST))OMO?(?!(MA|SIS))'

La idea es que reconozca el patron OM o OMO, pero que no se confunda con los otros patrones ESTOMAT o ESTOMATO, STOMATO o STOMATO.

Tal vez a alguien se le pueda ocurrir una manera diferente de reunir todos los patrones...

Gracias!!!
Katty
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2006-08-30 17:11 @757

Notapor explorer » 2006-09-05 18:29 @812

Un 'defecto' de las expresiones regulares extendidas '(?<= ...)' y '(?<! ...)' es que no admiten patrones de longitud variable.

En cuanto a lo que comentas, sería deseable saber además si los patrones están al principio, medio o final de palabra. O mezclas de estas posiciones.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor Katty » 2006-09-06 11:57 @539

Hola:

La verdad es que la entrada se puede exigir que sea de cierta manera, es decir, si solo funciona con letras mayusculas o minusculas se exige que la entrada sea de ese tipo.

Además, una duda que me surgio anoche, se podrá hacer que si una palabra no esta compuesta solo de patrones, sea capaz de reconocer lo que contenga y dejar el resto tal cual. Me explico con un ejemplo:

Si tenemos los patrones:

ADENO?
CARCINO?
EPI
OMA
ITIS


Si como entrada tenemos la siguiente palabra: EPIADENAL

La salida deberia ser EPI ADENAL, EPI (por el patron) y ADENAL por el resto de la palabra (que no coincide con ningún otro patron).

Saludos, Katty.
Katty
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2006-08-30 17:11 @757

Notapor explorer » 2006-09-06 12:14 @551

He encontrado una solución aún mejor.

El proceso ahora es el siguiente:
* Analizamos la palabra con los patrones
* Por cada patrón encontrado, lo sustituímos dentro de la palabra por la marca "[x]", siendo x un número que va incrementandose, porque lo sustituído entra en un array
* Si toda la palabra está compuesta de patrones, entonces las marcas nos indicarán el orden en que debemos pintar esos patrones.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl

$ao = '(A|O)';
$ior = '(O|IOR)';
$ico = "((O|IC$ao)S?)";

@patrones = (
                                        # Patrones de comienzo
    '^AN(?!(TE|GIO))',
    '^ANTI?(?!(E|TIS))',
    '^D(E|I)S?',
    '(?<=^EPI).+',
    '^EPI',
    '^EXTRA',
    '^EX(?!O|TERNO)',
    '^HIPER',
    '^HIPO',
    '^IM',
    '^INFRA',
    '^INTER(?!NO)',
    '^INTRA',
    '^IN(?!MUNO)',
    '^PER',
    '^POST?',
    '^PRE',
    '^SI(N|M)',
    '^SUPRA',
                                        # Patrones de final
    'ALGIA$',
    'EMIA$',
    'ITIS$',
    "OIDE$ao?S?\$",
    'ODINIA$',
    'OMAS?$',
    'OSIS$',

                                        # Patrones intermedios
    'A?BDOMIN(AL(ES)?|O)?',
    'ACRO?',
    'ADEN(OS?)?',
    "BLAST$ico?",
    'BRON(CO?|QUIO?)',
    'CARCINO?',
    'CARDIO',
    'CENTRO',
    "CIT$ico?",
    "CITARI$ao?S?",
    'EPI',
    'E?STOMATO?',
    'EXO',
    'HEMI?',
    "HEPAT$ico?",
    '(IN|EX)TERNO',
    "INFER$ior?",
    'INMUN(O|E)S?',
    'LEUCO?',
    'LINFO?',
    'MICRO?',
    'MIELO?',
    'MIO?',
    'OMO?',
    'PELVI?',
    'PULMON(ES|AR(IAS?)?)?',
    'SEMI',
    "SUPER$ior?",
    "TRI(C$ao?|QU)",
);

# Leemos el fichero de entrada
@lineas = <>;

# Por cada linea
foreach $linea ( @lineas ) {
    chomp $linea;
    @linea = ();

    # Por cada palabra
    foreach $palabra ( split(" ", $linea) ) {
        $mipalabra = $palabra;

        # Buscamos patrones dentro de la palabra,
        # haciendo sustituciones del $patron por una marca "[número]"
        #print "0: $mipalabra\n";
        @p = ();
        foreach $patron ( @patrones ) {
            $mipalabra =~ s/($patron)/push @p, $1; "[$#p]"/gie;
            #print "1: $mipalabra\n";
        }

        # Si $mipalabra contiene algún caracter distinto de "[número]"
        # entonces es una palabra normal y la guardamos tal cual
        if ( $mipalabra !~ /^[\[\]\d]+$/ ) { push @linea, $palabra }

        # Si está compuesta de patrones, hay que crear los
        # espacios en blanco entre ellos
        else {
            # Sacamos todas las @partes entre las marcas de $mipalabra
            @partes = $mipalabra =~ m/\[(\d+)\]/g;

            # Guardamos todas las @partes unidas por el separador
            push @linea, join("-", map { $p[$_] } @partes);
        }
    }

    # Final de linea, pintamos las palabras encontradas
    print join(" ", @linea),"\n";
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4
Prueba:
Código: Seleccionar todo
explorer@casa:~/Documents/Software/Perl> cat kk.txt
Adenocarcinoma
adenoma
acroma HOLA adenitis
ADENOACROMA
adenocarcino
amigdala
adenal
El enfermo, toma la dosis;
y retoma la cadena de medicamentos contra la artritis.
EXTRAHEPATO
INTRAHEPATO
HIPERHEPATO
HEPATICAS
HEPATICO
HEPATOMA
HEPATOSIS
ADENOSCARCINO
ESTOMATOMA
HIPERESTOMATO
STOMATOSIS
STOMATOMA
EXTRAABDOMINOCARCINOSIS
PERABDOMINO
PERMIELOMA
ADENOHEMOSIS
HEMIOMA
MICR
MICRO
BLASTOMA
HIPERMIOCARDIO
HIPOOMOCARCINOADENOHEMIABDOMINOSIS
EPIADENAL
BRONQUIOPULMON
CARCINOIDES
CENTROBLASTICOCENTROCITICO
INMUNOBLASTICO
INMUNOBLASTOMA
INTRAABDOMINALES
INTRABDOMINALES
LINFOIDES
SUPEROEXTERNO
SUPEROINTERNO
TRICOLEUCEMIA
TRICOLEUCOCITOS

explorer@casa:~/Documents/Software/Perl> ./kk.pl < kk.txt
Adeno-carcin-oma
aden-oma
acr-oma HOLA aden-itis
ADENO-ACR-OMA
adeno-carcino
amigdala
adenal
El enfermo, toma la dosis;
y retoma la cadena de medicamentos contra la artritis.
EXTRA-HEPATO
INTRA-HEPATO
HIPER-HEPATO
HEPATICAS
HEPATICO
HEPAT-OMA
HEPAT-OSIS
ADENOS-CARCINO
ESTOMAT-OMA
HIPER-ESTOMATO
STOMAT-OSIS
STOMAT-OMA
EXTRA-ABDOMINO-CARCIN-OSIS
PER-ABDOMINO
PER-MIEL-OMA
ADENO-HEM-OSIS
HEMI-OMA
MICR
MICRO
BLAST-OMA
HIPER-MIO-CARDIO
HIPO-OMO-CARCINO-ADENO-HEMI-ABDOMIN-OSIS
EPI-ADENAL
BRONQUIO-PULMON
CARCIN-OIDES
CENTRO-BLASTICO-CENTRO-CITICO
INMUNO-BLASTICO
INMUNO-BLAST-OMA
INTRA-ABDOMINALES
INTRA-BDOMINALES
LINF-OIDES
SUPERO-EXTERNO
SUPERO-INTERNO
TRICO-LEUC-EMIA
TRICO-LEUCO-CITOS
(He cambiado el " " por el "-" para ver mejor las separaciones)

El truco también está en poner los patrones dentro de @patrones en este orden:
* Primero, los patrones que sabemos que están siempre al principio o final de palabra (prefijos y sufijos), aquellos que tienen el '^' o el '$'.
* Luego, el resto de patrones.
Última edición por explorer el 2006-09-09 19:20 @847, editado 7 veces en total
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor explorer » 2006-09-06 13:29 @603

Katty escribiste:Además, una duda que me surgio anoche, se podrá hacer que si una palabra no esta compuesta solo de patrones, sea capaz de reconocer lo que contenga y dejar el resto tal cual.
Si como entrada tenemos la siguiente palabra: EPIADENAL
La salida deberia ser EPI ADENAL, EPI (por el patron) y ADENAL por el resto de la palabra (que no coincide con ningún otro patron).
Para este caso, vale con poner como patrones
'(?<=^EPI).+',
'^EPI',
justo después de los patrones de sufijos y prefijos.

El primer patrón captura todo lo que siga a '^EPI', y el segundo, el propio '^EPI'.

El problema lo tenemos ahora si lo que sigue a '^EPI' pueden ser más patrones, por lo que entonces el problema pasa de muy sencillo a complicado.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

En ciertas entradas NO se reconocen algunos patrones

Notapor Katty » 2006-09-09 12:10 @548

Hola:

Les escribo porque tengo un pequeño problema... y es que en algunas ocasiones algunos patrones no se reconocen como tal (no se genera la salida esperada) y en otras ocasiones si, y la verdad es que no se por que???

Para los siguientes patrones (que son una parte de la totalidad de ellos):


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
@patrones =
(       '^AN(?!(TE|GIO))',
        '^SI(N|M)',
        '^ANTI?(?!(E|TIS))',
        '^HIPER',
        '^HIPO',
        '^INTER(?!NO)',
        '^SUPRA',
        '^INFRA',
        '^DE|DES',
        '^EX(?!(O|TRA|TERNO))',
        '^EXTRA',
        '(?<!HI)PERI?', #       '^PERI?
        '^I(N|M)(?!(TRA|FRA|TERNO|FERO))',
        '^D(E|I)S?',
        '^POST?',
        '^PRE',
        '^INTRA',
        'DIS',

        '(ALGIA|ODINIA)$',
        'OIDE(A|O)?S?$',
        '(OSIS|OMAS?)$',
        'ITIS$',
       
        'EXTERNO(?!(MA|SIS|IDE))',
        'INTERNO(?!(MA|SIS|IDE))',
        'INFERI?(?!TIS)O(?!(MA|SIS|IDE))R?',
        'SUPERI?(?!TIS)O(?!(MA|SIS|IDE))R?',
        'EPI(?!TIS)',
        'EXO(?!(MA|SIS|IDE))',
        'CENTRO(?!(MA|SIS|IDE))',
                       
        'A?BDOMINO?(?!(MA|SIS|IDE))',
        'CARCINO?(?!(MA|SIS|IDE))',
        'PULMON(AR(IA)?)?E?S?',
        'BRON(CO?(?!(MA|SIS|IDE))|QUIO?(?!(MA|SIS|IDE)))',
        'BLAST(O(?!(MA|SIS|IDE))|IC(O(?!(MA|SIS|IDE))|A)?S?)?',
        'INMUN(O(?!(MA|SIS|IDE))|E)S?',
        'TRI(C(A|O(?!(MA|SIS|IDE)))?|QU)',
        'LINFO?(?!(MA|SIS|IDES))',
        'LEUCO?(?!(MA|SIS|IDE))',
'CIT(O(?!(MA|SIS|IDE))|IC(A|O(?!(MA|SIS|IDE)))|ARI(A|O(?!(MA|SIS|IDE))))?S?',
        'MIO?(?!(MA|SIS|IDE))',
    'OMO?(?!(MA|SIS|IDE))'
);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Para la entrada:

BRONQUIOPULMON
CARCINOIDES
CENTROBLASTICOCENTROCITICO
INMUNOBLASTICO
INMUNOBLASTOMA
INTRAABDOMINALES
INTRABDOMINALES
LINFOIDES
SUPEROEXTERNO
SUPEROINTERNO
TRICOLEUCEMIA
TRICOLEUCOCITOS


La salida deberia ser:

BRONQUIO PULMON
CARCIN OIDES
CENTRO BLASTICO CENTRO CITICO
INMUNO BLASTICO
INMUNO BLAST OMA
INTRA ABDOMINALES
INTRA BDOMINALES
LINF OIDES
SUPERO EXTERNO
SUPERO INTERNO
TRICO LEUC EMIA
TRICO LEUCO CITOS


Pero es como que no reconociera los patrones, por lo que la salida que se genera es lo mismo que la entrada.

Espero que me puedan ayudar...

Atte., Katty.
Katty
Perlero nuevo
Perlero nuevo
 
Mensajes: 16
Registrado: 2006-08-30 17:11 @757

Notapor explorer » 2006-09-09 17:33 @773

Estoy mirándolo pero hay que tener en cuenta un detalle: los patrones se analizan en secuencia -según está solución- por lo que si ponemos antes un determinado patrón, no es necesario ponerlo como excepción en el resto.

Ejemplo, con el prefijo 'EX' y 'EXTRA'. Si primero miramos por el patrón 'EXTRA' (lo colocamos antes en @patrones) antes que 'EX' quiere decir que podemos buscar por 'EX' y no por 'EX(?!TRA)', ya que, de existir 'EXTRA' en la palabra, ya ha sido localizada por el primer patrón.

Así que todas las excepciones de 'OMA', 'OSIS', 'OIDE' etc se podrían quitar.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor explorer » 2006-09-09 18:53 @829

Ya está.

He actualizado el mensaje 5278 con cambio en el programa. Como ves, ahora la salida es como quieres.

Lo que hay que tener en cuenta:
* Si colocamos los patrones que sabemos que son prefijos o sufijos al principio, no es necesario ponerles como excepciones en el resto de patrones.
* En el caso de que un prefijo o sufijo se puedan confundir con un patrón más importante, entonces sí que ponemos exclusiones (caso del patrón '^IN' que puede confundirse con el de 'INMUNO'. Por eso ponemos la excepción con 'IN(?!MUNO)' ).
* Algunos subpatrones se repiten, como '(A|O)' por ejemplo. Esos subpatrones se pueden poner como variables (al principio del programa) y ayudan bastante a simplificar los patrones (y reducir los posibles errores).

Otro pequeño detalle. Para contemplar el caso de 'CENTRO' repetido dos veces, he agregado '/g' al operador 's//'.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron