J'ai trois fichiers dont la plupart sont similairesinformations, mais un unique déposé. Je veux les combiner en un seul fichier. Les fichiers ont en commun les colonnes avec l'en-tête hs et les colonnes avec l'en-tête range1 et range2. Les colonnes différentes sont celles étiquetées f1c, f2c et f3c. Je veux combiner les fichiers en fonction des régions qui se chevauchent dans range1 et range2 (les colonnes hs doivent également correspondre dans cette situation).
Son comme les gammes sont deux barres, bar1 (hs1) a350 sections et bar2 (hs2) a 700 sections. Les valeurs sous f1c f2c et f3c tiennent toutes dans une certaine quantité de ces sections sur chaque barre. Pour les valeurs qui correspondent à la même section, je veux les énumérer les unes à côté des autres.
N'importe quel type de solution en bash, awk ou perl fonctionnerait, je ne sais simplement pas comment je peux faire correspondre ces choses en fonction des plages.
Voici un exemple des fichiers
Premier format de fichier
hs f1c range1 range2
hs1 p32 0 200
hs1 p31 200 300
hs1 p30 300 350
hs2 p32 0 300
hs2 p31 300 500
hs2 p30 500 700
Format du deuxième fichier
f2c hs range1 range2
DDX11L1 hs1 20 50
FAM41C hs1 50 70
WASH7P hs1 70 120
FAM138A hs1 180 250
OR4F5 hs2 0 50
KLHL17 hs2 50 100
PLEKHN1 hs2 100 150
LOC729737 hs2 300 500
HES4 hs2 500 600
ISG15 hs2 600 700
Troisième format de fichier
hs range1 range2 f3c
hs1 0 200 -1
hs1 200 350 -2
hs2 0 500 -1
hs2 500 700 -2
Voici un exemple de la sortie souhaitée (il y a un n sous f2c s'il n'y a pas de valeur dans file2 qui soit dans la plage)
hs f1c f2c range1 range2 f3c
hs1 p32 n 0 20 -1 // From the 1st line of file3, and the 1st line of file1
hs1 p32 DDX11L1 20 50 -1 // From the 1st line of file1, 1st line of file2 and 1st line of file3
hs1 p32 FAM41C 50 70 -1 // From the 1st line of file1, 2nd line of file2 and 1st line of file3
hs1 p32 WASH7P 70 120 -1 // 1st line file1, 3rd line file2, first line file3
hs1 p32 n 120 180 -1 // 1st line file1, 1st line file3
hs1 p32 FAM13BA 180 200 -1 // 1st line file1, 4th line file2, 1st line file3
hs1 p31 FAM13BA 200 250. -2 // 2nd line file1, 4th line file2, 2nd line file3
hs1 p31 n 250. 300 -2 // 2nd line file1, 2nd line file3
hs1 p30 n 300 350 -2 // 3rd line file1, 2nd line file3
hs2 p32 OR4FS 0 50 -1
hs2 p32 KLHL17 50 100 -1
hs2 p32 PLEKHN1 100 150 -1
hs2 p32 n 150 300 -1
hs2 p31 LOC729737 300 500 -1
hs2 p30 HES4 500 600 -2
hs2 p30 ISG15 600 700 -2
Je vous remercie
Réponses:
2 pour la réponse № 1J'ai écrit ceci pour vous aider, mais vous devezcomprenez que votre question est inacceptable sur un site qui offre gratuitement une aide au diagnostic. Vous ne pouvez pas simplement formuler votre demande et attendre qu'une solution gratuite de haute qualité apparaisse. J'ai écrit une réponse uniquement parce que c'est un jour férié dans mon pays et que le problème m'a intéressé
J'ai mis beaucoup plus d'efforts pour créer ceque vous ne l'avez manifestement écrit dans votre question, et vous n'avez même pas pris la peine de répondre aux nombreuses questions que les gens vous ont posées dans les commentaires
use strict;
use warnings "all";
use autodie;
use Readonly::Tiny "Readonly";
Readonly my @FILES => qw/ file1.txt file2.txt file3.txt /;
Readonly my $FORMAT => "%-6s%-6s%-10s%-5d%-5d%dn";
Readonly my @OUTPUT => qw/ hs f1c f2c range1 range2 f3c /;
Readonly my @KEY_COLUMNS => qw/ hs range1 range2 /;
my %data; # All the data for each value of `hs`
my %bounds; # All the values of `range1` or `range2` for each value of `hs`
my %heads; # All the headers found in any of the files
# From each file, read the header line and use the
# headers as keys for the data hashes representing each line
#
for my $file ( @FILES ) {
open my $fh, "<", $file; # Errors handled by `autodie`
my @head = split " ", <$fh>;
@heads{@head} = ();
while ( <$fh> ) {
next unless /S/;
my %row;
@row{@head} = split;
my ($hs, $r1, $r2) = @row{ @KEY_COLUMNS };
push @{ $data{$hs} }, %row;
++$bounds{$hs}{$_} for $r1, $r2;
}
}
# Change the `%bounds` hash values from
# hashes to sorted arrays of the boundary values
#
for ( values %bounds ) {
my @vals = sort {
my ($aa, $bb) = map { tr/0-9//cdr } $a, $b;
$aa <=> $bb;
} keys %$_;
$_ = @vals;
}
# Work through the `%bounds` hash
# printing a line of output for each range
#
for my $hs ( sort keys %bounds ) {
my $bounds = $bounds{$hs};
my $data = $data{$hs};
for my $i ( 1 .. $#$bounds ) {
my ($r1, $r2) = map { $bounds->[$_] } $i-1, $i;
my @matches = grep {
$r1 >= $_->{range1} and $r2 <= $_->{range2}
} @$data;
my %row;
for my $match ( @matches ) {
@row{ keys %$match } = values %$match;
}
@row{ @KEY_COLUMNS } = ($hs, $r1, $r2); # Overwrite in the new key values
printf $FORMAT, map { $_ // "n" } @row{ @OUTPUT };
}
}
sortie
hs1 p32 n 0 20 -1
hs1 p32 DDX11L1 20 50 -1
hs1 p32 FAM41C 50 70 -1
hs1 p32 WASH7P 70 120 -1
hs1 p32 n 120 180 -1
hs1 p32 FAM138A 180 200 -1
hs1 p31 FAM138A 200 250 -2
hs1 p31 n 250 300 -2
hs1 p30 n 300 350 -2
hs2 p32 OR4F5 0 50 -1
hs2 p32 KLHL17 50 100 -1
hs2 p32 PLEKHN1 100 150 -1
hs2 p32 n 150 300 -1
hs2 p31 LOC729737 300 500 -1
hs2 p30 HES4 500 600 -2
hs2 p30 ISG15 600 700 -2