공백으로 구분된 DNA 서열이 있습니다. 공백을 제거하고 공백 문자 없이 시퀀스 수를 반환해야 합니다. 이 작업을 수행하는 방법에 대한 도움이 있습니까? bash와 함께 터미널을 사용하고 있습니다.
예를 들어 시퀀스는 다음과 같습니다.
GTCGATTGCAAGGATCCGCATGGGATAAAGGAATCGCAGTTCGAACAGGCAATGCCGCAG
CTATGATAGGACATCTCTTGGAGACACCTATTAATGTTTCAGAAACGGATACCTTGGTTG
TCCAGTACGAAATTAAGTTGGACAATTCTTTGACGTGCGGC
CTATATTAAAATTGTGGGTACATCACTCTCTTACCTGAGAATTCCAACAGAGCAGGACGC
TAACCCAGTGTCTATACCAGTCTGTGGCTTTGAAAGATTAGACACATTTCTGGATGAATT
TTCAAATTCTAAATTGATCGTTCAGTCTACACTAAGACATTCGTACGTTAGTCTTGAGAA
공백을 제거하고 정확히 몇 개의 염기가 있는지 계산하고 싶습니다. 또는 A, C, G 또는 T가 몇 개나 있는지 계산하고 공백을 계산하지 않고 추가할 수 있습니다.
답변1
GNU awk를 사용하는 다중 문자 RS 및 RT:
$ awk -v RS='[^\n]' 'RT{cnt[RT]++} END{for (base in cnt) print base, cnt[base]}' file
A 101
C 68
T 98
G 74
귀하의 설명에서 "기본"은 귀하의 예에서 개행 문자가 아닌 모든 문자라고 가정합니다.
답변2
빈 줄이나 후행 공백 등이 없다고 가정하면 fold
개별 문자 스트림을 생성한 다음 sort
결합하여 uniq -c
다음을 사용하여 각 문자의 수를 계산할 수 있습니다.
$ fold -w 1 file | sort | uniq -c
101 A
68 C
74 G
98 T
입력에 정크 공백 문자가 있는 경우 초기 tr
단계를 사용하여 이러한 문자를 제거합니다.
$ tr -d -c 'ACGT' <file | fold -w 1 | sort | uniq -c
101 A
68 C
74 G
98 T
여기의 명령은 , 또는 를 제외한 tr
입력의 모든 문자를 제거합니다 .A
C
G
T
sort | uniq -c
파이프 끝에 있는 비트는 awk
입력에서 각 문자의 발생 횟수를 세고 다음을 보고하는 단일 명령 으로 대체될 수 있습니다 .
$ tr -d -c 'ACGT' <file | fold -w 1 | awk '{ count[$0]++ } END { for (ch in count) printf "%4d %s\n", count[ch], ch }'
101 A
68 C
74 G
98 T
그러나 우리가 그것을 도입하려고 한다면 awk
, 그것을 제거하는 것이 나을 수도 있습니다 fold
:
$ tr -d -c 'ACGT' <file | awk '{ for (i = 1; i <= length; ++i) count[substr($0,i,1)]++ } END { for (ch in count) printf "%4d %s\n", count[ch], ch }'
101 A
68 C
74 G
98 T
...다음과 같을 수도 있습니다 tr
:
$ awk '{ gsub("[^ACGT]", ""); for (i = 1; i <= length; ++i) count[substr($0,i,1)]++ } END { for (ch in count) printf "%4d %s\n", count[ch], ch }' file
101 A
68 C
74 G
98 T
awk
아름답게 인쇄된 코드 :
{
gsub("[^ACGT]", "") # removes anything not A, C, G, or T
for (i = 1; i <= length; ++i)
count[substr($0, i, 1)]++
}
END {
for (ch in count) {
printf "%4d %s\n", count[ch], ch
}
}
gsub()
대신 첫 번째 블록(입력의 각 줄을 구문 분석)을 다시 작성하여 사용할 수 있습니다 substr()
.
{
count["A"] += gsub("A", "A")
count["C"] += gsub("C", "C")
count["G"] += gsub("G", "G")
count["T"] += gsub("T", "T")
}
END {
for (ch in count) {
printf "%4d %s\n", count[ch], ch
}
}
...하지만 중첩된 코드가 약간 줄어든 것 외에는 이전 코드에 비해 크게 개선되지는 않을 것입니다(일부 사용자의 가독성에 도움이 되지 않는 한).
답변3
Perl 하나의 라이너를 사용하십시오.
perl -F'' -e '
BEGIN{my %h}
map { /\S/ and $h{$_}++ } @F;
END{print map { "$_ $h{$_}\n" } keys %h}
' file
산출
C 68
A 101
G 74
T 98
답변4
사용행복하다(이전 Perl_6)
raku -e '.say for slurp.comb(/\S/).Bag.pairs;'
예제 출력:
G => 74
T => 98
A => 101
C => 68
또는 탭으로 구분된 출력( .say
으로 변경 .put
):
~$ raku -e '.put for slurp.comb(/\S/).Bag.pairs;' file
G 74
A 101
T 98
C 68
출력을 정렬해야 하는 경우 .sort
끝에 다음을 추가하세요.
~$ raku -e '.put for slurp.comb(/\S/).Bag.pairs.sort;' file
A 101
C 68
G 74
T 98
또는 가장 높은 뉴클레오티드 수를 기준으로 정렬합니다.
~$ raku -e '.put for slurp.comb(/\S/).Bag.pairs.sort: -*.value;' file
A 101
T 98
G 74
C 68
아니면 그냥 세어보세요 (글꼴 없음공백):
~$ raku -e '.put for slurp.comb(/\S/).elems;' file
341
마지막으로, 매우 큰 파일로 작업하는 경우 더 나은 메모리 관리를 위해 lines.join
대신 을 사용해 볼 수 있습니다 .slurp
입력 예:
GTCGATTGCAAGGATCCGCATGGGATAAAGGAATCGCAGTTCGAACAGGCAATGCCGCAG
CTATGATAGGACATCTCTTGGAGACACCTATTAATGTTTCAGAAACGGATACCTTGGTTG
TCCAGTACGAAATTAAGTTGGACAATTCTTTGACGTGCGGC
CTATATTAAAATTGTGGGTACATCACTCTCTTACCTGAGAATTCCAACAGAGCAGGACGC
TAACCCAGTGTCTATACCAGTCTGTGGCTTTGAAAGATTAGACACATTTCTGGATGAATT
TTCAAATTCTAAATTGATCGTTCAGTCTACACTAAGACATTCGTACGTTAGTCTTGAGAA