Processar dados de texto simples

Processar dados de texto simples

Eu tenho esse arquivo de texto simples que preciso ser examinado automaticamente e os resultados escritos em outro arquivo de texto simples. Observe que usarei texto simples e CSV de forma intercambiável, pois CSVs são texto simples com separador comum entre dados (vírgulas, tabulações, etc.).

Exemplos de dados

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

Processe um- reconhecer as duas primeiras seções dos dados ( text- number) para repeti-las e contá-las no CSV de saída:

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

Processo dois- A primeira parte dos dados coletados acima possui uma espécie de chave primária atribuída a eles em um arquivo diferente. Gostaria de obter também as chaves primárias mencionadas nos arquivos recém-gerados:

#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

Então, basicamente, o que estou perguntando a ela é se existe algum software que possa me ajudar com isso em sistemas operacionais baseados em Windows ou Linux. O Bash pode me ajudar com um processamento mais simples, mas não acho que possa lidar com tanta coisa. Por favor, avise.

Responder1

  1. Escolha seu idioma preferido – Perl funciona bem com texto; Python, PHP e Ruby estão bem, embora um pouco mais lentos.
  2. Leia o arquivo-chave primeiro:
    • divida cada key,datalinha em keye data,
    • em seguida, armazene ambos em um dict/hash/array:keys[data] = key
    • também counts[data] = 0se a linguagem exigir inicialização
  3. Leia todos os arquivos de dados:
    1. use um regexp para encontrar os dados "TEXT-NUMBER" no início de cada linha,
    2. incrementar counts[data]em um,
    3. e imediatamente produza keys[data], a linha e counts[data].

Eu escrevi um script de exemplo em Perl e Python, então sua escolha:

processo.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);
}

processo.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)

Responder2

eu faria isso emPitãousandoexpressões regulares. Basta digitar pythonseu shell para ver se ele está instalado.

Caso contrário, você pode usarPerl. Basta digitar perlseu shell para ver se ele está instalado. É temsuporte integrado para expressões regulares.

Responder3

Processo 1

perl count.pl datafile …

onde count.pl é algo 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";
  }
}

Não testado, caveat emptor.

Processo 2

Adicione 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;
   }

e altere a linha de impressão END {}para

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

Novamente, não testado.

Você gerará avisos se o arquivo de dados contiver palavras-chave que não estejam no arquivo-chave. Você pode verificar se $key{$_}está indefinido e, em caso afirmativo, imprimir sem chave.

informação relacionada