perl fixed-length-record

¿Cómo leo los registros de longitud fija en Perl?



fixed-length-record (5)

Aquí hay otra forma de hacerlo:

while (<FILE>) { chomp; if (/^([A-Z]{5}) ([0-9]{3})$/) { $key = $1; $value = $2; } }

¿Cuál es la mejor manera de leer un registro de longitud fija en Perl? Sé leer un archivo como:

ABCDE 302 DEFGC 876

puedo hacer

while (<FILE>) { $key = substr($_, 0, 5); $value = substr($_, 7, 3); }

pero ¿no hay una forma de hacer esto con leer / descomprimir?


Independientemente de si sus registros y campos son de longitud fija, si los campos están separados por delimitadores uniformes (como un espacio o una coma), puede usar la función de división más fácilmente que desempaquetar.

my ($field1, $field2) = split / /;

Busque la documentación para dividir. Hay variaciones útiles en la lista de argumentos y en el formato del patrón del delimitador.


Suponga 10 registros de caracteres de dos campos de cinco caracteres por registro:

open(my $fh, "<", $filename) or die $!; while(read($fh, $buf, 10)) { ($field1, $field2) = unpack("A5 A5", $buf); # ... do something with data ... }


my($key, $value) = unpack "A5 A3"; # Original, but slightly dubious

Ambos debemos verificar las opciones en la página de manual de desempaquetado (y, más particularmente, en la página de manual del paquete ).

Como el operador del paquete A elimina los espacios en blanco finales, su ejemplo se puede codificar como:

my($key, $value) = unpack "A6A3";

Alternativamente (esto es Perl, entonces TMTOWTDI):

my($key, $blank, $value) = unpack "A5A1A3";

El 1 es opcional pero sistemático y simétrico. Una ventaja de esto es que puede validar esa $blank eq " " .


Actualización: para la respuesta definitiva, vea la respuesta de Jonathan Leffler a continuación.

No usaría esto solo para dos campos (usaría pack / unpack directamente), pero para 20 o 50 campos me gusta usar Parse :: FixedLength (pero estoy parcial). Ej. (Para su ejemplo) (Actualización: también, puede usar $ / y <> como una alternativa para leer ($ fh, $ buf, $ buf_length) ... ver a continuación):

use Parse::FixedLength; my $pfl = Parse::FixedLength->new([qw( key:5 blank:1 value:3 )]); # Assuming trailing newline # (or add newline to format above and remove "+ 1" below) my $data_length = $pfl->length() + 1; { local $/ = /$data_length; while(<FILE>) { my $data = $pfl->parse($_); print "$data->{key}:$data->{value}/n"; # or print $data->key(), ":", $data->value(), "/n"; } }

Hay algunos módulos similares que hacen que pack / unpack sea más "amigable" (Consulte la sección "Ver también" de Parse :: FixedLength).

Actualización: Guau, esta fue una respuesta alternativa, no la respuesta oficial ... bueno, ya que es lo que es, debería incluir algo del código más directo de Jonathan Leffler, que es cómo debería hacerlo normalmente. (ver paquete / desempaquetar documentos y el nodo de Jonathan Leffler a continuación):

$_ = "ABCDE 302"; my($key, $blank, $value) = unpack "A5A1A3";