Procesar datos en texto plano

Procesar datos en texto plano

Tengo este archivo de texto sin formato que necesito examinar automáticamente y escribir los resultados en otro archivo de texto sin formato. Tenga en cuenta que usaré texto sin formato y CSV indistintamente, ya que los CSV son texto sin formato con un separador común entre datos (comas, tabulaciones, etc.).

Ejemplos de datos

ABD-01A
ABD-01B
ABD-01C
AL-25A
AL-25B

Proceso uno- reconocer las dos primeras secciones de los datos ( text- number) para repetirlas y contarlas en el CSV de salida:

ABD-01,1
ABD-01,2
ABD-01,3
AL-25,1
AL-25,2

Proceso dos- La primera parte de los datos recopilados anteriormente tiene una especie de clave principal asignada en un archivo diferente. También me gustaría obtener las claves principales mencionadas en los archivos recién generados:

#primary key file
1,ABD-01
2,ABD-02
3,AL-02
20,AL-25

#newly generated file
1,ABD-01,1
1,ABD-01,2
1,ABD-01,3
20,AL-25,1
20,AL-25,2

Básicamente, lo que le pregunto es si hay algún software que pueda ayudarme con esto en sistemas operativos basados ​​en Windows o Linux. Bash puede ayudarme con un procesamiento más sencillo, pero no creo que pueda manejar tanto. Por favor avise.

Respuesta1

  1. Elija su idioma preferido: Perl funciona bien con texto; Python, PHP y Ruby están bien, aunque un poco más lentos.
  2. Lea primero el archivo clave:
    • dividir cada key,datalínea en keyy data,
    • luego almacene ambos en un dict/hash/array:keys[data] = key
    • también counts[data] = 0si el lenguaje exige inicialización
  3. Leer todos los archivos de datos:
    1. use una expresión regular para encontrar los datos "NÚMERO DE TEXTO" al principio de cada línea,
    2. incrementar counts[data]en uno,
    3. e inmediatamente genera keys[data], la línea y counts[data].

Escribí un script de ejemplo tanto en Perl como en Python, así que tu elección:

proceso.pl

#!/usr/bin/env perl
use strict;

sub usage {
    print "Usage: $0 <key_file> <data_file...>\n";
    return 2;
}

my $keys_file = shift(@ARGV) // exit(usage);
my @data_files = @ARGV;

my %keys;   # $data => $primarykey
my %counts; # $data => $count

# Read keys

open(my $fh, "<", $keys_file) or die "$!";
while (my $line = <$fh>) {
    chomp($line);
    my ($key, $datum) = split(/,/, $line, 2);
    if (!defined $datum) {
        warn "$keys_file: line $. not in KEY,DATA format: '$line'\n";
        next;
    }

    $keys{$datum} = $key;
    $counts{$datum} = 0;
}
close($fh);

# Read and output data

my $ex = qr/^(\w+-\d+)\w*/;
for my $data_file (@data_files) {
    open(my $fh, "<", $data_file) or die "$!";
    while (my $line = <$fh>) {
        chomp($line);
        if ($line =~ /$ex/) {
            my $datum = $1;
            if (!defined $keys{$datum}) {
                warn "no primary key found for data '$datum'\n";
                next;
            }

            # Increment count, then print processed line immediately
            $counts{$datum}++;
            print "$keys{$datum},$&,$counts{$datum}\n";
        }
        else {
            warn "$data_file: line $. does not begin with TEXT-NUMBER: '$_'\n";
        }
    }
    close($fh);
}

proceso.py

#!/usr/bin/env python
from __future__ import print_function
import sys
import re

def usage():
    print("Usage: %s <key_file> <data_file...>" % sys.argv[0])
    return 2

try:
    keys_file = sys.argv[1]
    data_files = sys.argv[2:]
except IndexError:
    sys.exit(usage())
except ValueError:
    sys.exit(usage())

keys = {}
counts = {}

# Read keys

for line in open(keys_file, "r"):
    try:
        key, datum = line.strip().split(",", 1)
    except ValueError:
        print("%s: line not in KEY,DATA format: %r" \
            % (keys_file, line.strip()), file=sys.stderr)
        continue

    keys[datum] = key
    counts[datum] = 0

# Read and output data

ex = re.compile(r'^(\w+-\d+)\w*')
for data_file in data_files:
    for line in open(data_file, "r"):
        line = line.strip()
        m = re.match(ex, line)
        if m:
            datum = m.group(1)
            if datum not in keys:
                print("no primary key found for data %r" % datum,
                    file=sys.stderr)
                continue

            # Increment count, then print processed line immediately
            counts[datum] += 1
            print("%s,%s,%d" % (keys[datum], m.group(0), counts[datum]))
        else:
            print("%s: line does not begin with TEXT-NUMBER: %r" \
                % (data_file, line.strip()), file=sys.stderr)

Respuesta2

lo haría enPitónusandoexpresiones regulares. Simplemente escriba pythonsu shell para ver si está instalado.

De lo contrario puedes usarperla. Simplemente escriba perlsu shell para ver si está instalado. Es decir tienesoporte incorporado de expresiones regulares.

Respuesta3

Proceso 1

perl count.pl datafile …

donde count.pl es algo así como

#!perl
use strict;
use warnings;

my %headwordcount;

while (<>) {
  if (/^([A-Z]+-\d+)/) { $headwordcount{$1}++; }
  # else { warn "Bad data: $_"; } # uncomment line for data warnings
}

END {
  foreach (sort keys %headwordcount) {
     print "$_,$headwordcount{$_}\n";
  }
}

No probado, advertencia emptor.

Proceso 2

Agrega algo como

   my %key;

   BEGIN {
     my $keyfilename = 'primary.key';
     open my $fh, '<', $keyfilename or die "Can't read '$keyfilename' - $!\n";
     while (<$fh>) {
        chomp;
        my ($key,$headword) = split(/,/, $_, 2);
        $key{$headword} = $key;        
     }
     close $fh;
   }

y cambie la línea de impresión END {}a

   print "$key{$_},$_,$headwordcount{$_}\n";

De nuevo, sin probar.

Generará advertencias si el archivo de datos contiene encabezados que no están en el archivo clave. Puede verificar si $key{$_}no está definido y, de ser así, imprimir sin clave.

información relacionada