J'ai deux fichiers délimités par des tabulations, le fichier 1 contient des identifiants et le fichier 2 a des valeurs liées à ces identifiants (ou dire que c'est un très gros dictionnaire).
Fichier 1
Ronny Rubby Suzie Paul
Le fichier 1 n'a qu'une seule colonne.
Fichier 2
Alistar Barm Cathy Paul Ronny Rubby Suzie Tom Uma Vai Zai 12 13 14 12 11 11 12 23 30 0.34 0.65 1 4 56 23 12 8.9 5.1 1 4 25 3
N nombre de lignes sont présentes dans le fichier 2.
Ce que je veux, si les identifiants du fichier 1 sont présents dans le fichier 2, je devrais avoir toutes les valeurs qui lui sont liées dans un autre fichier délimité par des tabulations.
Quelque chose comme ça:
Paul Ronny Rubby Suzie 12 11 11 12 23 12 8.9 5.1
Merci d'avance.
7 réponses
Un exemple en Python qui fait le travail en stream (ie: pas besoin de charger le fichier complet avant de démarrer la sortie):
# read keys
with open('file1', 'r') as fd:
keys = fd.read().splitlines()
# output keys
print '\t'.join(keys)
# read data file, with header line and content
with open('file2', 'r') as fd:
headers = fd.readline().split()
while True:
line = fd.readline().split()
if len(line) == 0:
break
print '\t'.join([line[headers.index(x)] for x in keys if x in headers])
Production:
$ python test.py
Ronny Ruby Suzie Paul
11 11 12 12
12 8.9 5.1 23
REMARQUE
Votre exemple de sortie n'est PAS correct, car là vous avez "Ruby" mais dans votre exemple file1 vous aviez "Rubby" Ruby = / = Rubby
kent$ awk 'NR==FNR{t[$0]++;next}
{if(FNR==1){
for(i=1;i<=NF;i++)
if($i in t){
v[i]++;
printf $i"\t";
}
print "";
}else{
for(x in v)
printf $x"\t"
print "";
}
}' file1 file2
sortie
Paul Ronny Suzie
12 11 12
23 12 5.1
$ awk 'FILENAME~1{a[$0];next};FNR==1{for(i=1;i<=NF;i++)if($i in a)b[i]};{for(j in b)printf("%s\t",$j);print ""}' file{1,2}.txt
Paul Ronny Suzie
12 11 12
23 12 5.1
Diviser en plusieurs lignes et ajouter un espace blanc
$ awk '
> FILENAME~1 { a[$0]; next }
> FNR==1 { for(i=1; i<=NF; i++) if($i in a) b[i] }
> { for(j in b) printf("%s\t",$j); print ""}
> ' file{1,2}.txt
Paul Ronny Suzie
12 11 12
23 12 5.1
Quelque chose comme ça pourrait probablement fonctionner, selon ce que vous voulez.
use strict;
use warnings;
my %names;
open ( my $nh, '<', $name_file_path ) or die "Could not open '$name_file_path'!";
while ( <$nh> ) {
m/^\s*(.*?\S)\s*$/ and $names{ $1 } = 1;
}
close $nh;
my $coln = -1;
open ( my $dh, '<', $data_file_path ) or die "Could not open '$data_file_path'!";
my ( @name_list, @col_list )
my @names = split /\t/, <$dh>;
foreach my $name ( 0..$#names ) {
next unless exists $names{ $names[ $name ] };
push @name_list, $name;
push @col_list, $coln;
}
local $" = "\t";
print "@name_list\n";
print "@{[ split /\t/ ]}[ @col_list ]\n" while <$dh>;
close $dh;
Cela pourrait fonctionner pour vous:
sed '1{s/\t/\n/gp};d' file2 |
nl |
grep -f file1 |
cut -f1 |
paste -sd, |
sed 's/ //g;s,.*,cut -f& /tmp/b,' |
sh
Explication:
- Faire pivoter les noms des colonnes
- Numéroter les noms des colonnes
- Faites correspondre les noms de colonne avec le fichier d'entrée.
- Laissez tomber les noms de colonne en conservant les numéros de colonne.
- Faites pivoter les numéros de colonne séparés par des
,
. - Créez une commande
cut
à partir de la liste des numéros de colonne séparés par des virgules. - Exécutez la commande
cut
sur le fichier de données.
Vous pouvez utiliser uniquement bash pour le faire:
FIELDS=`head -1 f2.txt | tr "\t" "\n" | nl -ba | grep -f f1.txt | cut -f1 | tr -d " " | tr "\n" ","`; FIELDS=${FIELDS/%,/}
cut -f$FIELDS f2.txt
Paul Ronny Ruby Suzie
12 11 11 12
23 12 8.9 5.1
Solution Perl:
#!/usr/bin/perl
use warnings;
use strict;
open my $KEYS, '<', 'file1' or die $!;
my @keys = <$KEYS>;
close $KEYS;
chomp @keys;
my %is_key;
undef @is_key{@keys};
open my $TAB, '<', 'file2' or die $!;
$_ = <$TAB>;
my ($i, @columns);
for (split) {
push @columns, $i if exists $is_key{$_};
$i++;
}
do {{
my @values = split;
print join("\t", @values[@columns]), "\n";
}} while <$TAB>;
Questions connexes
De nouvelles questions
python
Python est un langage de programmation multi-paradigme, typé dynamiquement et polyvalent. Il est conçu pour être rapide à apprendre, comprendre, utiliser et appliquer une syntaxe propre et uniforme. Veuillez noter que Python 2 est officiellement hors support à partir du 01-01-2020. Néanmoins, pour les questions Python spécifiques à la version, ajoutez la balise [python-2.7] ou [python-3.x]. Lorsque vous utilisez une variante Python (par exemple, Jython, PyPy) ou une bibliothèque (par exemple, Pandas et NumPy), veuillez l'inclure dans les balises.