아래와 같이 엄청난 양의 데이터가 있습니다.
파일 1(4600줄)
Genome Gene Boolean
E15-12 VFG000923 1
E15-13 VFG000924 1
E15-14 VFG000926 1
E15-15 VFG000928 1
E15-16 VFG000930 1
E15-17 VFG000932 1
E15-18 VFG000933 0
E15-19 VFG001448 0
E15-24 VFG013465 1
col2의 정보를 다음과 같이 분류하고 싶습니다.
파일 2(180줄)
VFG000923|fepA
VFG000924|fepB
VFG000926|fepD
VFG000928|fepG
VFG000930|entF
VFG000932|entE
VFG000933|entB
VFG001448|kpsD
VFG001450|kpsM
VFG044165|entS
나가
Genome Gene Boolean
E15-12 VFG000923|fepA 1
E15-13 VFG000924|fepB 1
E15-14 VFG000926|fepD 1
E15-15 VFG000928|fepG 1
E15-16 VFG000930|entF 1
E15-17 VFG000932|entE 1
E15-18 VFG000933|entB 0
E15-19 VFG001448|kpsD 0
E15-20 VFG001450|kpsM 1
@val0x00ff의 코드 사용(댓글 참조)
Genome Gene Boolean
E15-14 VFG000923|fepA 1
E15-14 VFG000924|fepB 0
E15-14 VFG000926|fepD 1
E15-14 VFG000928|fepG 0
sed나 awk를 사용하여 이를 수행할 수 있는 방법이 있습니까?
답변1
그리고 sed
:
sed '/|/{H;d;};G;s/\([A-Z0-9]*\)\(.*\n\)\1\(|[^[:cntrl:]]*\)/\1\3\2\1\3/;P;d' FILE2 FILE1
그러면 문제가 해결될 것입니다. 이건 적응이야이 답변. 자세한 설명이 나와있습니다.
답변2
이것은 작동합니다:
$ awk 'NR==FNR{k=sub(/\|.*/,$1); a[k]=$1; next} ($2 in a){$2=a[$2]}1' file2 file
Genome Gene Boolean
E15_14 VFG000923|fepA 1
E15_14 VFG000924|fepB 1
E15_14 VFG000926|fepD 0
E15_14 VFG000928|fepG 1
E15_14 VFG000930|entF 0
E15_14 VFG000932|entE 0
E15_14 VFG000933|entB 1
E15_14 VFG001448|kpsD 1
E15_14 VFG001450|kpsM 1
E15_14 VFG044165|entS 0
또는 읽기가 더 쉽습니다.
awk 'NR==FNR{
k=sub(/\|.*/,$1);
a[k]=$1;
next
}
($2 in a){
$2=a[$2]
}1' file2 file
설명하다
NR==FNR{ }
: NR은 현재 입력 라인 번호이고, FNR은 현재 파일의 라인 번호입니다. 여러 파일을 읽을 때 두 파일은 첫 번째 파일을 읽을 때만 동일합니다.k=sub(/\|.*/,$1);
:줄에서 다음 부분을 제거합니다|
(위에서 언급한 것처럼 이는 첫 번째 파일에서만 발생하므로NR==FNR
).a[k]=$1;
: 첫 번째 파일의 첫 번째 필드를 키가 유전자 이름인 배열의 값으로 저장합니다 (a
첫 번째 필드|
이후의 모든 항목은 제거됨).next
: 다음 줄로 이동합니다. 이렇게 하면 첫 번째 파일을 읽는 동안 다음 블록을 실행하지 않게 됩니다.($2 in a)
: 두 번째 필드가 배열의 키로 존재하는 경우a
(두 번째 파일에 대해서만 실행됩니다)$2=a[$2]
: 두 번째 필드를a
for 에 저장된 항목 으로 설정합니다$2
.1
: 이것은 "현재 줄 인쇄"에 대한 awk의 약어입니다. awk의 내용이 true로 평가되면 기본 작업은 현재 줄을 인쇄하는 것이기 때문에 작동합니다. 항상 true 이므로1
인쇄됩니다.
답변3
perl -lne '
@ARGV and %h=(%h, /(.*)\|/ => $_),next;
!@ARGV and !$a++ and print,next;
print s//$h{$1}/r if exists $h{(/\h\K(\S+)(?=\h)/)[0]};
' FILE2 FILE1
설명하다
- 더 작은 파일(FILE2)을 읽을 때 이전 데이터의 해시를 채우고
%h
값은 전체 라인입니다.keyed
|
- 더 큰 파일(FILE1)을 읽을 때 먼저 다음을 사용하여 첫 번째 줄을 인쇄합니다.
!@ARGV and !$a++
의미가 지워졌고@ARGV
처음으로 변수를 볼 수 있습니다.$a
- 나머지 행에서는 식별된 두 번째 필드를 통해
regex
/\h\S+\h/
키가 해시에 존재하는지 확인합니다%h
. 이것이 사실인 것으로 확인되면 필드를 해당 키에 해당하는 값으로 바꿉니다.