각 파일의 첫 번째 열에 공통 문자열이 있는 행만 포함되도록 필터링하려는 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 결과만 인쇄하고 파일을 다시 쓰지는 않지만 쉽게 변경할 수 있습니다.