arreglo array regex perl split

regex - array - Divida los datos con 3 delimitadores y guárdelos en 2 matrices separadas a la vez



perl substring (2)

Tengo datos con 3 delimitadores (:, y;) Y en los datos: y; aparecer solo una vez

__DATA__ 1:X,Y,X,A,B;C,D,E,F 2:A,C,B,D 3:W,R,T,E;E

Paso 1:

Dividir por: y crear un hash

Paso 2:

Dividir por y almacenar cada valor separado por comas en una matriz hasta que encontremos;

Paso 3:

Todo lo que sigue; estaría en otra matriz

De los datos anteriores, estoy tratando de almacenar todos los valores antes; en el conjunto A y todo a la derecha en el conjunto B

Output A = [X,Y,X,B,A,B,C,D,W,R,T,E] B=[C,D,E,F,E]

A continuación está el código que probé

my (@A,@B); sub Compare_results { my %result_hash = map { chomp; split '':'', $_ } <DATA> ; #split by colon and futher split by , and ; if any (doing it in insert_array) foreach my $key ( sort { $a <=> $b } (keys %result_hash) ) { @A = split ",", (/([^;]+)/)[0], $result_hash{$key}; @B = split ",", (/;([^;]+)/)[0], $result_hash{$key}; print Dumper /@A,/@B; } }

Pero esto no está produciendo ningún resultado. Las matrices de salida están vacías. ¿Cuál es el enfoque correcto para dividir datos por y? en un momento almacenar en una matriz separada ¿Hay también una manera de dividir datos por tres delimitadores (una división para construir un hash) de una vez

Gracias


El truco es hacer cada paso por separado y en un orden diferente. El orden es tokenize luego analizar . Básicamente, divídelo en pedazos, luego haz algo con esas piezas.

El siguiente truco es tokenizar recursivamente . Eso es, en lugar de intentar tokenizar todo de una vez, dividir tokens grandes en tokens más pequeños, y convertirlos en tokens más pequeños, y así sucesivamente hasta que toques fondo. Primero la línea, luego los CSV.

Mirándolo de esta manera, la primera capa de la gramática se ve más o menos así (se ignora el espacio en blanco).

LINE = LINENUM : CSV ; CSV

Tenga en cuenta que en este momento no nos importa lo que hay en el CSV. Asumiremos que no tenemos que lidiar con las citas y escapar, sino que las cosas se complican.

Hay algunas maneras de lidiar con esto. Una es usar una expresión regular para tokenizar todo en una sola toma.

my($linenum, @csvs) = $line =~ /^(.*?) : ([^;]*) ; (.*)$/x;

Ahora que tiene los @csvs separados de todo lo demás, necesitan ser tokenizados. Puede convertirlos en más fichas dividiendo en comas.

push @$a, split /,/, $csvs[0]; push @$b, split /,/, $csvs[1];

Y ahí tienes. Al tokenizar cada capa, se evita la complejidad de intentar analizar todo de una vez.

En cuanto a su función, hay muchas cosas que se pueden hacer para mejorarla. En su mayoría tienen que hacer una cosa , analizar el archivo. Algo más abre el archivo.

Además, todo lo que necesita debe pasarse y devolverse, sin usar elementos globales (sí, my desde fuera de la función cuenta como global).

use strict; use warnings; use v5.10; # for say() my($left, $right) = parse_whatever_this_format_is_called(*DATA); say "Left: ". join ", ", @$left; say "Right: ". join ", ", @$right; sub parse_whatever_this_format_is_called { # Take the filehandle to read as input my $fh = shift; # Declare our outputs my(@left, @right); # Parse each line while( my $line = <$fh>) { # Tokenize LINE = LINENUM : CSV ; CSV my($linenum, @csvs) = $line =~ /^(.*?) : ([^;]*) ; (.*)$/x; # Skip lines that didn''t match next if !$linenum; # Split the CSVs push @left, split /,/, $csvs[0]; push @right, split /,/, $csvs[1]; } # Return our outputs as references. # It''s the only way to return multiple lists. # Also it avoids the expense of a copy. return( /@left, /@right ); } __DATA__ 1:X,Y,X,A,B;C,D,E,F 2:A,C,B,D 3:W,R,T,E;E


Muchos problemas: open necesita un nombre de archivo, no contenido de manejo de archivos (a menos que DATA contenga el nombre del archivo, que no). Para mantener los valores en las matrices, use push , not assignment; de todos modos, no puede asignar dos matrices al mismo tiempo, ya que el primero se come todo. Además, hacer todo en un comando podría ser posible, pero definitivamente no legible y mantenible.

#!/usr/bin/perl use warnings; use strict; my $fh = *DATA{IO}; my (@A, @B); # The comments just fix # the stupid SO syntax highlighter. my %result_hash = map { chomp; split /:/ } <$fh>; #/ for my $key (sort { $a <=> $b } keys %result_hash) { my ($left, $right) = split /;/, $result_hash{$key}; #/ push @A, split /,/, $left; #/ push @B, split /,/, $right // q(); } use Data::Dumper; print Dumper(/@A, /@B, /%result_hash); __DATA__ 1:X,Y,X,A,B;C,D,E,F 2:A,C,B,D 3:W,R,T,E;E