0

たとえば、5 つの数字 => [1,2,3,4,5] と 3 つのグループがあります

ファイル 1 (グループ 1):

1
3
5

ファイル 2 (グループ 2):

3
4

ファイル3(グループ3):

1
5

出力 (列 1: グループ 1 内かどうか、列 2: グループ 2 内かどうか、列 3: グループ 3 内かどうか [NA は、ないことを意味します]):

1 NA 1
3 3 NA
NA 4 NA
5 NA 5

または、次のようなもの (+ は入っていることを意味し、- は入っていないことを意味します):

1 + - +
3 + + -
4 - + -
5 + - +

joinとを試しましたが、どちらも複数のmergeファイルに対してうまく機能しないようです..(たとえば、8ファイル)

4

4 に答える 4

2

あなたは 1 から 5 の数字があると言っていますが、これは、私が見る限り、あなたが望む出力とは無関係です。ファイルで見つかった数値のみを出力に使用します。このコードはあなたが望むことをします:

use strict;
use warnings;
use feature 'say';

my @hashes;
my %seen;
local $/;   # read entire file at once
while (<>) {
    my @nums = split;                          # split file into elements
    $seen{$_}++ for @nums;                     # dedupe elements
    push @hashes, { map { $_ => $_ } @nums };  # map into hash
}

my @all = sort { $a <=> $b } keys %seen;       # sort deduped elements
# my @all = 1 .. 5;                            # OR: provide hard-coded list

for my $num (@all) {                           # for all unique numbers
    my @fields;
    for my $href (@hashes) {                   # check each hash
        push @fields, $href->{$num} // "NA";   # enter "NA" if not found
    }
    say join "\t", @fields;                    # print the fields
}

のソートされた重複排除済みリストを、他の有効なリストに置き換えることができ@allます。my @all = 1 .. 5次に、それらの数値の行を追加し、欠落している値の追加の「NA」フィールドを出力します。

また、これはファイルの内容が数値であるという事実に依存していることに注意する必要がありますが、@all配列のソートに関してのみであるため、独自のリストまたは独自のソートルーチンに置き換えると、任意の値を使用します。

このスクリプトは、任意の数のファイルを取得して処理します。例えば:

$ perl script.pl f1.txt f2.txt f3.txt
1       NA      1
3       3       NA
NA      4       NA
5       NA      5

OP の意味を理解したBrent Stewartの功績によるものです。

于 2013-02-26T17:32:05.760 に答える
0

入力ファイルが単調に増加し、入力サンプルが示すように各行に単一の整数のみで構成されている場合は、入力ファイルを前処理して貼り付けを使用できます。

for i in file{1,2,3}; do  # List input files
  awk '{ a += 1; while( $1 > a ) { print "NA"; a += 1 }} 1' $i > $i.out
done
paste file{1,2,3}.out

これにより、一部の列の末尾のエントリが空のままになります。それを修正することは、読者の演習として残されています。

于 2013-02-26T18:11:08.893 に答える
0

2 つのファイルの場合、以下に示すように簡単に使用できます (とがソートされているとjoin仮定します)。file1file2

$ join -e NA -o 1.1,2.1 -a 1 -a 2  file1 file2
1 NA
3 3
NA 4
5 NA

ただし、2 つ以上のファイルがある場合は、さらに複雑になります。

ブルートフォースgrepソリューションは次のとおりです。

#!/bin/bash
files=(file1 file2 file3)
sort -nu "${files[@]}" | while read line; do
    for f in "${files[@]}"; do   
         if grep -qFx "$line" "$f"; then
             printf "${line}\t"
         else
             printf "NA\t"
         fi
    done
    printf "\n"
done

出力:

1       NA      1
3       3       NA
NA      4       NA
5       NA      5
于 2013-02-26T16:43:03.243 に答える
0
#!/usr/bin/env perl
use strict;
use warnings;
use autodie;

my @lines;
my $filecount = 0;

# parse
for my $filename (@ARGV){
  open my $fh, '<', $filename;
  while( my $line = <$fh> ){
    chomp($line);
    next unless length $line;
    $lines[$line][$filecount]++;
  }
  close $fh;
}continue{
  $filecount++;
}

# print
for my $linenum ( 1..$#lines ){
  my $line = $lines[$linenum];
  next unless $line;

  print ' ' x (5-length $linenum), $linenum, ' ';

  for my $elem( @$line ){
    print $elem ? 'X' : ' '
  }
  print "\n";
}
    1 X X
    3 XX
    4  X
    5 X X
于 2013-02-26T17:11:21.303 に答える