file
다음과 같은 탭으로 구분된 항목이 있습니다 .
$ cat file
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558474.1 1155234 1156286 polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558475.1 1156298 1156807 12 carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558476.1 1156804 1157820 -3 oxidoreductase [Mycobacterium]
여기서 1155234
, 1156286
, 1156298
및 1156807
뒤에는 탭 1156804
문자가 옵니다 1157820
(즉, 여섯 번째(마지막) 열을 제외하고는 파일에 공백이 없습니다). 0
다섯 번째 열에 탭 문자를 추가하고 첫 번째 행과 여섯 번째 열 끝의 탭 문자를 공백으로 바꾸고 싶습니다 . 출력은 다음과 같습니다.
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558474.1 1155234 1156286 0 polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558475.1 1156298 1156807 12 carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558476.1 1156804 1157820 -3 oxidoreductase [Mycobacterium]
awk나 sed를 사용하여 이 작업을 어떻게 수행할 수 있나요?
답변1
탭으로 구분된 열이 6개 있는 것처럼 보이지만 5열의 값이 누락되어 일부 처리에서 6열의 첫 번째 단어를 5열에 남겨 두었습니다. 이는 탭 대신 공백이나 일반 공백을 구분 기호로 사용하는 이전 처리 단계 때문일 수 있습니다.
이제 열 5에 0을 삽입하고 단어를 열 6의 올바른 위치로 이동하려고 합니다.
나는 파일이 다음과 같다고 가정합니다. 여기서 각각은 탭 문자입니다(이것은 ^I
파일의 출력입니다).cat -t
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558474.1^I1155234^I1156286^Ipolyketide^Isynthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558475.1^I1156298^I1156807^I12^Icarboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558476.1^I1156804^I1157820^I-3^Ioxidoreductase [Mycobacterium]
빈 열 2가 있는지는 확실하지 않습니다. 그렇다면 아래에 사용한 열 번호에 하나를 추가하세요.
$ awk -F '\t' 'BEGIN { OFS=FS } $5 ~ /[[:alpha:]]/ { $6 = $5 " " $6; $5 = 0 } { print }' file
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558474.1 1155234 1156286 0 polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558475.1 1156298 1156807 12 carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558476.1 1156804 1157820 -3 oxidoreductase [Mycobacterium]
awk
여기서는 다섯 번째 열의 문자를 감지하는 데 사용하고 있습니다 . 그렇다면 5열 앞에 공백을 추가하여 6열을 구분하고 5열을 0으로 설정하세요. 그런 다음 수정 여부에 관계없이 모든 행을 출력합니다.
답변2
귀하의 답변은 기본적으로 귀하가 요청한 내용을 수행하지만 개선될 수 있습니다.
합리적인 범위 내에서 (간단한) 명령 수와 파이프 수를 최소화하려고 합니다. 필요한 것보다 더 많이 갖는 것은 비효율적일 수 있습니다. 5줄 또는 10줄 파일에서는 이를 눈치채지 못하지만, 백만 줄 파일을 처리할 때는 차이가 있습니다.
sed
두 개의 명령(하나는 다른 명령으로 파이프됨)을 실행할 필요가 없습니다 . 넌 할 수있어sed-e'(첫 번째 에스 주문하다)'-이자형'(두번째 에스 주문하다)'
또는sed'(첫 번째 에스 주문하다) ; (두번째 에스 주문하다)'
- 예제 출력에서 탭이 첫 번째 줄에서만 공백이 되도록 하려는 것으로 나타나므로 명령
s/\t/ /
앞에도1
. - 동작은
s/…/…/6g
정의되지 않았습니다. (6번째 탭에서) 한 번만 하고 싶기 때문에 (없이)s/\t/ /
만 말해야 합니다.s/\t/ /6
g
).
그래서 당신의 명령은
sed '1s/\t/\t0\t/4'문서
중괄호를 사용하면 수행하려는 명령을 그룹화할 수 있습니다. 그래서 당신도 말할 수 있습니다
sed '1{s/\t/\t0\t/4s/\t/ /6}'문서
앗
다음과 같이 awk에서 이 작업을 수행할 수 있습니다.
awk -F '\t' -v OFS='\t' 'NR==1 { $6 = $5 " " $6 = "0"} { 인쇄 } '문서
답변3
splice
다음과 같이 장면에 내장된 함수를 사용하여 배열을 쪼개고 쪼갤 수 있습니다.
$ perl -F\\t -pale '
next unless $. == 1;
splice @F, 4, 2, 0, join $", @F[-2,-1];
$_ = join "\t", @F;
' input.file
답변4
잘 작동하는 다음 명령을 사용해보십시오.
awk 'NR==1 {$8=$7;$7=$6;$6=$5;$5=0}1' filename| sed -r "s/\s+/ /g"| sed "s/ /\t/g
"
산출
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558474.1 1155234 1156286 0 polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558475.1 1156298 1156807 12 carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn WP_011558476.1 1156804 1157820 -3 oxidoreductase [Mycobacterium]