Domanda

Sto elaborando un enorme file con (GNU) awk , (altri strumenti disponibili sono: strumenti shell Linux, alcune vecchie versioni (> 5.0) di Perl, ma non riesco ad installare i moduli ).

Il mio problema: se alcuni field1, field2, field3 contengono X, Y, ZI è necessario cercare un file in un'altra directory che contiene field4 e field5 su una riga e inserire alcuni dati dal file trovato nell'output corrente.

per esempio:.

Riga file effettiva:

f1 f2 f3 f4 f5
X  Y  Z  A  B

Ora devo cercare un altro file (in un'altra directory), che contiene ad esempio

f1 f2 f3 f4
A  U  B  W

E scrivi a STDOUT $ 0 dal file originale e f2 e f3 dal file trovato, quindi elabora la riga successiva del file originale.

È possibile farlo con awk ?

È stato utile?

Soluzione

Vorrei iniziare dicendo che la descrizione del problema non è poi così utile. La prossima volta, ti preghiamo di essere più specifico: potresti perdere soluzioni molto migliori.

Quindi dalla tua descrizione, ho capito che hai due file che contengono dati separati da spazi bianchi. Nel primo file, si desidera abbinare le prime tre colonne a un modello di ricerca. Se trovato, si desidera trovare tutte le righe in un altro file che contengono la quarta e la quinta colonna della riga corrispondente nel primo file. Da quelle righe, è necessario estrarre la seconda e la terza colonna e quindi stampare la prima colonna del primo file e la seconda e la terza dal secondo file. Va bene, ecco qui:

#!/usr/bin/env perl -nwa
use strict;
use File::Find 'find';
my @search = qw(X Y Z);

# if you know in advance that the otherfile isn't
# huge, you can cache it in memory as an optimization.

# with any more columns, you want a loop here:
if ($F[0] eq $search[0]
    and $F[1] eq $search[1]
    and $F[2] eq $search[2])
{
  my @files;
  find(sub {
      return if not -f 

Vorrei iniziare dicendo che la descrizione del problema non è poi così utile. La prossima volta, ti preghiamo di essere più specifico: potresti perdere soluzioni molto migliori.

Quindi dalla tua descrizione, ho capito che hai due file che contengono dati separati da spazi bianchi. Nel primo file, si desidera abbinare le prime tre colonne a un modello di ricerca. Se trovato, si desidera trovare tutte le righe in un altro file che contengono la quarta e la quinta colonna della riga corrispondente nel primo file. Da quelle righe, è necessario estrarre la seconda e la terza colonna e quindi stampare la prima colonna del primo file e la seconda e la terza dal secondo file. Va bene, ecco qui:

<*>

A differenza della soluzione di un altro poster che contiene molte chiamate di sistema, questo non ricade affatto nella shell e quindi dovrebbe essere molto veloce.

; # verbatim search for the columns in the file name. # I'm still not sure what your file-search criteria are, though. push @files, $File::Find::name if /\Q$F[3]\E/ and /\Q$F[4]\E/; # alternatively search for the combination: #push @files, $File::Find::name if /\Q$F[3]\E.*\Q$F[4]\E/; # or search *all* files in the search path? #push @files, $File::Find::name; }, '/search/path' ) foreach my $file (@files) { open my $fh, '<', $file or die "Can't open file '$file': $!"; while (defined(

Vorrei iniziare dicendo che la descrizione del problema non è poi così utile. La prossima volta, ti preghiamo di essere più specifico: potresti perdere soluzioni molto migliori.

Quindi dalla tua descrizione, ho capito che hai due file che contengono dati separati da spazi bianchi. Nel primo file, si desidera abbinare le prime tre colonne a un modello di ricerca. Se trovato, si desidera trovare tutte le righe in un altro file che contengono la quarta e la quinta colonna della riga corrispondente nel primo file. Da quelle righe, è necessario estrarre la seconda e la terza colonna e quindi stampare la prima colonna del primo file e la seconda e la terza dal secondo file. Va bene, ecco qui:

<*>

A differenza della soluzione di un altro poster che contiene molte chiamate di sistema, questo non ricade affatto nella shell e quindi dovrebbe essere molto veloce.

= <$fh>)) { chomp; # order of fields doesn't matter per your requirement. my @cols = split ' ',

Vorrei iniziare dicendo che la descrizione del problema non è poi così utile. La prossima volta, ti preghiamo di essere più specifico: potresti perdere soluzioni molto migliori.

Quindi dalla tua descrizione, ho capito che hai due file che contengono dati separati da spazi bianchi. Nel primo file, si desidera abbinare le prime tre colonne a un modello di ricerca. Se trovato, si desidera trovare tutte le righe in un altro file che contengono la quarta e la quinta colonna della riga corrispondente nel primo file. Da quelle righe, è necessario estrarre la seconda e la terza colonna e quindi stampare la prima colonna del primo file e la seconda e la terza dal secondo file. Va bene, ecco qui:

<*>

A differenza della soluzione di un altro poster che contiene molte chiamate di sistema, questo non ricade affatto nella shell e quindi dovrebbe essere molto veloce.

; my %seen = map {(

Vorrei iniziare dicendo che la descrizione del problema non è poi così utile. La prossima volta, ti preghiamo di essere più specifico: potresti perdere soluzioni molto migliori.

Quindi dalla tua descrizione, ho capito che hai due file che contengono dati separati da spazi bianchi. Nel primo file, si desidera abbinare le prime tre colonne a un modello di ricerca. Se trovato, si desidera trovare tutte le righe in un altro file che contengono la quarta e la quinta colonna della riga corrispondente nel primo file. Da quelle righe, è necessario estrarre la seconda e la terza colonna e quindi stampare la prima colonna del primo file e la seconda e la terza dal secondo file. Va bene, ecco qui:

<*>

A differenza della soluzione di un altro poster che contiene molte chiamate di sistema, questo non ricade affatto nella shell e quindi dovrebbe essere molto veloce.

=>1)} @cols; if ($seen{$F[3]} and $seen{$F[4]}) { print join(' ', $F[0], @cols[1,2]), "\n"; } } close $fh; } } # end if matching line

A differenza della soluzione di un altro poster che contiene molte chiamate di sistema, questo non ricade affatto nella shell e quindi dovrebbe essere molto veloce.

Altri suggerimenti

Questo è il tipo di lavoro che mi ha portato a passare da awk a perl in primo luogo. Se hai intenzione di farlo, potresti effettivamente trovare più semplice creare uno script shell che crei uno o più script awk per interrogare e quindi aggiornare in passaggi separati.

(Ho scritto una tale bestia per leggere / aggiornare file in stile Windows - è brutto. Vorrei poter usare perl.)

Vedo spesso la restrizione "Non riesco a usare alcun modulo Perl" e, quando non è una domanda di compiti a casa, spesso è solo a causa della mancanza di informazioni. Sì, anche tu puoi usare CPAN contiene le istruzioni su come installare i moduli CPAN localmente senza avere i privilegi di root . Un'altra alternativa è solo prendere il codice sorgente di un modulo CPAN e incollarlo nel tuo programma.

Niente di tutto ciò aiuta se esistono altre restrizioni non dichiarate, come la mancanza di spazio su disco che impedisce l'installazione di (troppi) file aggiuntivi.

Questo sembra funzionare per alcuni file di test che ho impostato corrispondenti ai tuoi esempi. Coinvolgere il perl in questo modo (interposto con grep) probabilmente danneggerà molto la performance, sebbene ...

## perl code to do some dirty work

for my $line (`grep 'X Y Z' myhugefile`) {
    chomp $line;
    my ($a, $b, $c, $d, $e) = split(/ /,$line);
    my $cmd = 'grep -P "' . $d . ' .+? ' . $e .'" otherfile';
    for my $from_otherfile (`$cmd`) {
        chomp $from_otherfile;
        my ($oa, $ob, $oc, $od) = split(/ /,$from_otherfile);
        print "$a $ob $oc\n";
    }
}

MODIFICA: usa la soluzione di tsee (sopra), è molto più ben congegnata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top