各ファイルの最初の列に共通の文字列を含む行のみを含めるようにフィルタリングしたい24個のファイルがあります(例では、geneAとgeneFはColumn1の各ファイルに共通の唯一の文字列です)。出力には3つの列を維持する必要があります。ファイルはタブで区切られます。
私のファイルは次のとおりです。
ファイル1.txt
Column1 Column2 Column3
geneA 11 C
geneB 34 T
geneC 22 A
geneD 23 A
geneE 2 G
geneF 34 A
ファイル2.txt
Column1 Column2 Column3
geneA 34 A
geneF 67 G
geneG 77 A
geneZ 45 G
geneY 99 T
ファイル24.txt
Column1 Column2 Column3
geneA 22 A
geneF 7 T
geneL 34 C
geneK 66 A
geneM 34 T
geneP 47 G
私が望む出力は次のとおりです。
ファイル1.txt
Column1 Column2 Column3
geneA 11 C
geneF 34 A
ファイル2.txt
Column1 Column2 Column3
geneA 34 A
geneF 67 G
ファイル24.txt
Column1 Column2 Column3
geneA 22 A
geneF 7 T
答え1
"내부" 편집을 위해 GNU awk를 사용하면 주어진 컬럼1 값이 입력 파일에 여러 번 나타날 수 있는 경우에도 작동합니다.
$ cat tst.awk
BEGIN {
for (fileNr=1; fileNr<ARGC; fileNr++) {
file = ARGV[fileNr]
delete thisFile
while ( (getline < file) > 0 ) {
thisFile[$1]
if ( fileNr == 1 ) {
common[$1]
}
}
close(file)
for ( val in common ) {
if ( !(val in thisFile) ) {
delete common[val]
}
}
}
}
(FNR == 1) || ($1 in common)
.
$ awk -i inplace -f tst.awk file{1..3}
$ tail -n +1 file{1..3}
==> file1 <==
Column1 Column2 Column3
geneA 11 C
geneF 34 A
==> file2 <==
Column1 Column2 Column3
geneA 34 A
geneF 67 G
==> file3 <==
Column1 Column2 Column3
geneA 22 A
geneF 7 T
그러나 column1 값이 각 파일에 한 번만 나타날 수 있는 경우에는 더 짧아질 수 있습니다.
$ awk -i inplace -v comm="$(cut -f1 file{1..3} | sort | uniq -c | awk '$1==3')" '
BEGIN{split(comm,tmp); for (i in tmp) common[tmp[i]]} (FNR == 1) || ($1 in common)
' file{1..3}
또는 내부 편집 기능이 있는 awk가 없는 경우:
$ comm="$(cut -f1 file{1..3} | sort | uniq -c | awk '$1==3')"
$ for file in file{1..3}; do
awk -v comm="$comm" '
BEGIN{split(comm,tmp); for (i in tmp) common[tmp[i]]} (FNR == 1) || ($1 in common)
' "$file" > tmp && mv tmp "$file"
done
答え2
하나의 라이너(조인을 사용하는 /bin/sh 또는 /bin/bash용):
tmp=$(cat file1); for f in file{2..3}; do tmp=$(join -j1 -o1.1 <(echo "${tmp}"|sort) <(sort $f)); done; for f in file{1..3}; do echo "> File $f:"; for i in $(echo $tmp); do grep "^$i\s" $f; done; done
산출:
> File file1:
Column1 Column2 Column3
geneA 11 C
geneF 34 A
> File file2:
Column1 Column2 Column3
geneA 34 A
geneF 67 G
> File file3:
Column1 Column2 Column3
geneA 22 A
geneF 7 T
설명하다:
#!/bin/sh
# find first column members existing in each file
tmp=$(cat file1);
for f in file{2..3}; do
tmp=$(join -j1 -o1.1 <(echo "${tmp}"|sort) <(sort $f));
done;
#
# going through files and printing lines containing found members
for f in file{1..3}; do
echo "> File $f:";
for i in $(echo $tmp); do
grep "^$i\s" $f;
done;
done
PS 결과만 인쇄하고 파일을 다시 쓰지는 않지만 쉽게 변경할 수 있습니다.