
最後の列が同じである必要があるテキストファイルの連続した行を比較するには?そして、2番目の列の1つ以上の値が一致してはいけません。
- 一致するものがある場合は、まずファイルの列6を比較してください。
- 次に、列4で一致する行を比較します。列4のすべての値は同じではなく、少なくとも1つの値は異なる必要があります。ここで、HSF1とHIF1ANはライン1、2、3に位置しています。
入力ファイル
chr10 102979 103832 HSF1 305
chr10 102979 103832 HIF1AN 1 305
chr10 102979 103832 HSF1 305
chr10 103124438 103124851 HSF1 471
chr10 103124438 103124851 EGLN1 2 471
chr10 103969896 103970503 HSF1 472
chr10 103969896 103970503 HSF1 472
chr10 39135037 39142175 HSF1 335
chr10 4191461 4191936 HSF1 309
chr10 4191461 4191936 HSF1 309
chr10 42423355 42424014 HSF1 336
結果ファイル
chr10 102979 103832 HSF1 305
chr10 102979 103832 HIF1AN 1 305
chr10 102979 103832 HSF1 305
chr10 103124438 103124851 HSF1 471
chr10 103124438 103124851 EGLN1 2 471
答え1
タブ区切りファイルを想定すると、GNU awkを使用できます。
gawk -F'\t' 'NR == FNR {count[$6][$4]++; next} length(count[$6]) > 1' file file
chr10 102979 103832 HSF1 305
chr10 102979 103832 HIF1AN 1 305
chr10 102979 103832 HSF1 305
chr10 103124438 103124851 HSF1 471
chr10 103124438 103124851 EGLN1 2 471
これはファイルを2回通過します。 1 つ目は、各 $6 に何個の $4 値が発生するかを計算し、2 番目は $6 に複数の $4 値がある場合にレコードを出力します。
単一パスで行うことも可能ですが、複雑さ、メモリ使用量、元の順序が失われる可能性があります。
Perlの同じ論理
perl -Mautodie -e '
open $f, "<", shift;
while (<$f>) {
@F = split /\t/;
$c{ $F[5] }{ $F[3] }++;
}
# re-process the file
seek $f, 0, 0;
while (<$f>) {
@F = split /\t/;
print if scalar keys %{ $c{$F[5]} } > 1;
}
' file
答え2
ファイルを1行ずつ読み込み、最後の列の値がバッファ内の他のすべての行と同じ場合はその行をバッファに保存し、それ以外の場合はバッファを処理して空にします。
バッファを処理することは、4番目の列の値を共有しない少なくとも1組の連続行を見つけ、成功した場合にバッファを印刷することを意味します。
より良い出力を取得し、値にアクセスしやすくするために、個々の列とともに正確な行をバッファに格納します。
#!/usr/bin/perl
use warnings;
use strict;
sub process {
my (@rows) = @_;
my $different;
for my $i (1 .. $#rows) {
$different = 1, last if $rows[ $i - 1 ][4] ne $rows[$i][4];
}
print map "$_->[0]\n", @rows if $different;
}
my @buffer;
while (<>) {
chomp;
my @columns = split;
if (! @buffer || $buffer[0][-1] == $columns[-1]) {
push @buffer, [$_, @columns];
} else {
process(@buffer);
@buffer = [$_, split];
}
}
process(@buffer);