извлечение данных из словаря - PullRequest
0 голосов
/ 08 декабря 2011

У меня есть два файла с разделителями табуляции, файл 1 содержит идентификаторы, а файл 2 содержит значения, связанные с этими идентификаторами (или, скажем, это очень большой словарь).

файл 1

Ronny
Rubby
Suzie
Paul

файл 1 имеет только один столбец.

файл 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 количество строк в файле 2.

что я хочу, если в файле 2 присутствуют идентификаторы файла 1, у меня должны быть все связанные с ним значения в другом файле с разделителями табуляции.

Примерно так:

Paul Ronny Rubby Suzie
12     11   11   12
23     12   8.9  5.1

Заранее спасибо.

Ответы [ 7 ]

4 голосов
/ 08 декабря 2011

ПРИМЕЧАНИЕ

ваш пример вывода НЕ верен, так как там у вас есть "Ruby", но в вашем примере file1 у вас был "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

выход

Paul    Ronny   Suzie
12      11      12
23      12      5.1
2 голосов
/ 08 декабря 2011

Вы можете использовать только bash для этого:

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
2 голосов
/ 08 декабря 2011
$ 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

разбить на несколько строк && добавить пробел

$ 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
1 голос
/ 09 декабря 2011

Это может работать для вас:

 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

Объяснение:

  1. Поворот имен столбцов
  2. Нумерация имен столбцов
  3. Соответствиеимена столбцов по отношению к входному файлу.
  4. Разделить имена столбцов, сохраняя номера столбцов.
  5. Повернуть номера столбцов, разделяя их ,.
  6. Построить cut команда из списка номеров столбцов, разделенных запятыми.
  7. Запустите команду cut для файла данных.
1 голос
/ 08 декабря 2011

Нечто подобное может работать, в зависимости от того, что вы хотите.

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;
1 голос
/ 08 декабря 2011

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>;
1 голос
/ 08 декабря 2011

Пример в Python, который выполняет работу в потоке (т.е.: не нужно загружать полный файл перед началом вывода):

# 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])

Выход:

$ python test.py 
Ronny   Ruby    Suzie   Paul
11      11      12      12
12      8.9     5.1     23
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...