こんにちは。テーブルファイルがあります(区切り記号= \t
)A.txt
。
205 toto patho
207 tata benign
208 titi likely_patho
そしてB.txt
:
210 lolo patho
211 lala benign
212 lili benign
3番目の列が「patho」または「likely_patho」の場合、2番目の列の値を印刷するファイルが必要です。この例では、次のようになります。
A toto;titi
B lolo
そのために、私は次のことをしました。
for bla in *.txt; do
r="$(basename -s ".txt" $bla)"
awk -v filename=$r '($3=="patho" || $3=="likely_patho") {print filename"\t"$2}' $bla >> result.txt ;
done
ただし、ファイルに複数の一致(たとえばA.txt
)が含まれている場合、このコードは各一致に対して1行を提供します。
A toto
A titi
B lolo
どうすれば正しい出力を得ることができますか?ありがとう
答え1
awkを使用してください。
$ cat tst.awk
BEGIN {
split(t,tmp)
for ( i in tmp ) {
tgts[tmp[i]]
}
FS = OFS = "\t"
}
FNR == 1 {
fname = FILENAME
sub(/\.[^.]*$/,"",fname)
}
$3 in tgts {
hits[fname] = (fname in hits ? hits[fname] ";" : "") $2
}
END {
for ( fname in hits ) {
print fname, hits[fname]
}
}
$ awk -v t='patho likely_patho' -f tst.awk *.txt
A toto;titi
B lolo
答え2
努力する:
awk ' FNR==1 { f=FILENAME;
sub(/\.[^.]*$/,"",f);
printf "%s%s\t",aline,f;
aline="\n";
s=""
}
($3=="patho" || $3=="likely_patho"){
printf "%s%s",s,$2;
s="; "
}
END{print ""}
' ./*.txt
答え3
試してみてください(1行だけです)。
awk -v filename="$r" 'BEGIN { string=filename "\t" }
($3=="patho" || $3=="likely_patho") {printf string $2; string=";" }
END { printf "\n" } ' $bla >> result.txt ;
私はstring
プレフィックスとして使用し、ファイル名を最初に印刷してからセミコロンを印刷します。
最後の改行文字を追加する必要があります。
答え4
Perlを使う(読みやすくするために改行を使う):
$ perl -MFile::Basename -F'\t' -le '
$f = fileparse($ARGV, qw(.txt)) if $. == 1;
if ($F[2] =~ /^(likely_)?patho$/) {
push @{ $files{$f} }, $F[1]
};
close(ARGV) if eof; # close each input file and reset the line counter $. at eof
END {
foreach (sort keys %files) {
print "$_\t", join(";",@{ $files{$_} })
}
}' A.txt B.txt
A toto;titi
B lolo
-MFile::Basename
Perlにロードするように指示するファイル::デフォルト名基準寸法。これはPerlに含まれるコアPerlモジュールです。-F
フィールド区切り文字(タブ)を設定し、Perlの-a
自動分割モード(各入力行をawkと同様に名前付き配列に分割@F
)と、-n
入力を繰り返すPerlのオプション(sed -n
と同様に動作awk
)も有効にします。-l
行末自動処理を有効にします(\n
デフォルト)。つまり、各入力行の末尾から改行文字を削除し(Perlのchomp()
関数を使用して)、それを各ステートメントの最後に追加しますprint
。すべてのPerlコマンドラインオプションはで説明されています
man perlrun
。
スクリプトは各入力行を繰り返し、3番目のフィールドで一致するものが見つかるたびに($F[2]
-perl配列インデックスは0から始まります)、2番目のフィールドを(HoA)middleという配列ハッシュに追加します%files
。これは、キーがデフォルトのファイル名で値が2番目のフィールドの文字列配列であるハッシュ(連想配列)です。 Perlデータ構造の詳細についてはperldata
、perllol
およびのマニュアルページを参照してください。perldsc
すべての入力を読み取り、処理したら、要求された形式でファイル名でソートされたデータを出力します。
注:... if $. == 1;
このclose(ARGV) if eof
行とともに、各新しいファイルの最初の行からデフォルトのファイル名のみが抽出されていることを確認してください。これは必須ではなく、非常に大きな入力ファイルがある場合にのみ役立つ小さな最適化です。少し短い行を好む場合やパフォーマンスが問題にならない場合は、行とclose(ARGV) ...
条件if $. == 1
を削除してください。