/ / Rechercher / lire un autre fichier depuis awk en fonction du contenu du fichier actuel, est-ce possible? - perl, recherche, shell, awk, interface de ligne de commande

La recherche / lecture d'un autre fichier depuis awk en fonction du contenu du fichier actuel, est-ce possible? - perl, recherche, shell, awk, interface de ligne de commande

Je traite un gros fichier avec (GNU) awk, (les autres outils disponibles sont: les outils du shell Linux, certaines anciennes versions (> 5.0) de Perl, mais ne peuvent pas installer de modules).

Mon problème:si certains field1, field2, field3 contiennent X, Y, Z je dois rechercher un fichier dans un autre répertoire qui contient field4 et field5 sur une ligne, et insérer des données du fichier trouvé dans la sortie courante.

Par exemple.:

Ligne de fichier réelle:

f1 f2 f3 f4 f5
X  Y  Z  A  B

Maintenant, je dois rechercher un autre fichier (dans un autre répertoire), qui contient par exemple

f1 f2 f3 f4
A  U  B  W

Et écrivez à STDOUT $0 à partir du fichier d'origine, et f2 et f3 à partir du fichier trouvé, puis traitez la ligne suivante du fichier d'origine.

Est-il possible de le faire avec awk?

Réponses:

2 pour la réponse № 1

Permettez-moi de commencer par dire que la description de votre problème n'est pas vraiment utile. La prochaine fois, soyez plus précis: vous risquez de manquer de bien meilleures solutions.

Donc, d'après votre description, je comprends que vous avezdeux fichiers contenant des données séparées par des espaces. Dans le premier fichier, vous voulez faire correspondre les trois premières colonnes avec un modèle de recherche. Si trouvé, vous voulez trouver toutes les lignes dans un autre fichier qui contiennent les quatrième et cinquième colonnes de la ligne correspondante dans le premier fichier. À partir de ces lignes, vous devez extraire la deuxième et la troisième colonne, puis imprimer la première colonne du premier fichier et la deuxième et la troisième à partir du deuxième fichier. D'accord, voici:

#!/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 $_;
# 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($_ = <$fh>)) {
chomp;
# order of fields doesn"t matter per your requirement.
my @cols = split " ", $_;
my %seen = map {($_=>1)} @cols;
if ($seen{$F[3]} and $seen{$F[4]}) {
print join(" ", $F[0], @cols[1,2]), "n";
}
}
close $fh;
}
} # end if matching line

Contrairement à la solution d'un autre poster qui contient beaucoup d'appels système, cela ne revient pas du tout au shell et devrait donc être très rapide.


1 pour la réponse № 2

C'est le type de travail qui m'a amené à quitterawk en perl en premier lieu. Si vous prévoyez d'accomplir cela, vous trouverez peut-être plus facile de créer un script shell qui crée des scripts awk à interroger puis à mettre à jour en étapes séparées.

(J'ai écrit une telle bête pour lire / mettre à jour des fichiers de style Windows ini - c'est moche. J'aurais aimé pouvoir utiliser perl.)


1 pour la réponse № 3

Je vois souvent la restriction "Je ne peux" pas utiliser de modules Perl ", et quand ce n'est pas une question de devoir, c'est souvent juste à cause d'un manque d'informations. Oui, même vous pouvez utiliser CPAN contient les instructions sur la façon d'installer les modules CPAN localement sans avoir les privilèges root. Une autre alternative consiste simplement à prendre le code source d'un module CPAN et à le coller dans votre programme.

Rien de tout cela n'aide s'il existe d'autres restrictions non déclarées, comme le manque d'espace disque, qui empêchent l'installation de (trop) fichiers supplémentaires.


0 pour la réponse № 4

Cela semble fonctionner pour certains fichiers de test que j'ai configurés pour correspondre à vos exemples. Impliquer perl de cette manière (interposé avec grep) va probablement nuire considérablement à la performance, cependant ...

## 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 $ocn";
}
}

MODIFIER: Utilisez la solution de tsee (ci-dessus), c'est beaucoup plus bien pensé.