문자열의 위치를 ​​변경하여 출력 목록 생성

문자열의 위치를 ​​변경하여 출력 목록 생성

나는 약 30 길이의 짧은 문자열(DNA 서열)을 다루고 있습니다. 내 목적에 따르면 모든 5번째 위치는 4개의 DNA 염기(A,C,T,G) 중 하나로 대체되어야 합니다. 예를 들어 입력이 있으면 AAAAAAAAAAAAAA 출력은 다음 목록이 됩니다.

AAAAAAAAAAAAAA
AAAACAAAAAAAAA
AAAATAAAAAAAAA
AAAAGAAAAAAAAA
AAAACAAAACAAAA
AAAACAAAATAAAA
....

즉, 모든 5번째 위치는 A, C, T 또는 G로 교환되어 가능한 모든 서열의 배열을 생성하며, 여기서 모든 5번째 위치는 가능한 모든 DNA 염기입니다.

for 루프를 사용하려고 했는데 다섯 번째 위치마다 편집할 수 있지만 결합된 방법에서는 편집할 수 없습니다.

예를 들어

echo "AAAAAAAAAAAAAAA" > one.spacer 
for i in $(seq 1 3)
  do
    for base in {a,c,t,g}
      do
       awk -v b=$base -v x=$i '{print substr ($0,1,5*x-1) b substr ($0,5*x+1,100)}' one.spacer
    done
done

출력은 다음과 같습니다.

AAAAaAAAAAAAAAA
AAAAcAAAAAAAAAA
AAAAtAAAAAAAAAA
AAAAgAAAAAAAAAA
AAAAAAAAAaAAAAA
AAAAAAAAAcAAAAA
AAAAAAAAAtAAAAA
AAAAAAAAAgAAAAA
AAAAAAAAAAAAAAa
AAAAAAAAAAAAAAc
AAAAAAAAAAAAAAt
AAAAAAAAAAAAAAg

하지만 5번째 위치마다 개별적으로만 편집되는 것을 볼 수 있기를 바랍니다. 예를 들어 다음을 포함하는 시퀀스 목록이 필요합니다.

AAAAgAAAAgAAAAg
AAAAcAAAAtAAAAa

그리고 다른 모든 조합. 이것이 조금 더 명확해지기를 바랍니다.

답변1

모든 Unix 시스템의 모든 쉘에서 awk를 사용하여 실제 30자 너비 입력의 경우에도 1초 이내에 실행됩니다.

$ cat tst.awk
function mutate(old,lgth,       new,i,j) {
    for (i=5; i<=lgth; i+=5) {
        for (j=1; j<=4; j++) {
            new = substr(old,1,i-1) substr("ACTG",j,1) substr(old,i+1)
            if ( !seen[new]++ ) {
                print new
                mutate(new,lgth)
            }
        }
    }
}

{ mutate($0,length($0)) }

$ echo 'AAAAAAAAAAAAAAA' | awk -f tst.awk
AAAAAAAAAAAAAAA
AAAACAAAAAAAAAA
AAAATAAAAAAAAAA
AAAAGAAAAAAAAAA
AAAAGAAAACAAAAA
AAAAAAAAACAAAAA
AAAACAAAACAAAAA
AAAATAAAACAAAAA
AAAATAAAATAAAAA
AAAAAAAAATAAAAA
AAAACAAAATAAAAA
AAAAGAAAATAAAAA
AAAAGAAAAGAAAAA
AAAAAAAAAGAAAAA
AAAACAAAAGAAAAA
AAAATAAAAGAAAAA
AAAATAAAAGAAAAC
AAAAAAAAAGAAAAC
AAAACAAAAGAAAAC
AAAAGAAAAGAAAAC
AAAAGAAAAAAAAAC
AAAAAAAAAAAAAAC
AAAACAAAAAAAAAC
AAAATAAAAAAAAAC
AAAATAAAACAAAAC
AAAAAAAAACAAAAC
AAAACAAAACAAAAC
AAAAGAAAACAAAAC
AAAAGAAAATAAAAC
AAAAAAAAATAAAAC
AAAACAAAATAAAAC
AAAATAAAATAAAAC
AAAATAAAATAAAAT
AAAAAAAAATAAAAT
AAAACAAAATAAAAT
AAAAGAAAATAAAAT
AAAAGAAAAAAAAAT
AAAAAAAAAAAAAAT
AAAACAAAAAAAAAT
AAAATAAAAAAAAAT
AAAATAAAACAAAAT
AAAAAAAAACAAAAT
AAAACAAAACAAAAT
AAAAGAAAACAAAAT
AAAAGAAAAGAAAAT
AAAAAAAAAGAAAAT
AAAACAAAAGAAAAT
AAAATAAAAGAAAAT
AAAATAAAAGAAAAG
AAAAAAAAAGAAAAG
AAAACAAAAGAAAAG
AAAAGAAAAGAAAAG
AAAAGAAAAAAAAAG
AAAAAAAAAAAAAAG
AAAACAAAAAAAAAG
AAAATAAAAAAAAAG
AAAATAAAACAAAAG
AAAAAAAAACAAAAG
AAAACAAAACAAAAG
AAAAGAAAACAAAAG
AAAAGAAAATAAAAG
AAAAAAAAATAAAAG
AAAACAAAATAAAAG
AAAATAAAATAAAAG

답변2

이는 좋은 쉘 코딩 관행으로 간주되는 것에서 크게 벗어나고 아마도 비효율적이며 큰 입력에 맞게 확장되지 않습니다. 그러나 간결성을 위해 ksh93 쉘을 사용하고 기본값을 가정하면 $IFS다음을 수행할 수 있습니다.

words=($(<your-file))
printf '%s\n' ${words[@]//{4}(?)?/\1{A,C,T,G}}

를 사용하여 ${var//pattern/replacement}4자 + 1의 각 시퀀스를 4자로 대체하고 {A,C,T,G}ksh에서 따옴표가 없는 인수 확장은 csh 중괄호 확장 다음에 끝납니다.

답변3

Python의 모듈에는 itertools이러한 조합 문제를 처리하는 여러 가지 방법이 있습니다.

python3 - <<\eof
import itertools as it

dna = 'atcg'
step = 5

with open('yourfile') as f:
  for _ in f:
    l = _.rstrip('\n')
    w = len(l)
    I = [i for i in range(step-1,w,step)]
    for t1 in  it.product(dna,repeat=int(w/step)):
      t = list(t1)[::-1]
      print(*[
        t.pop(0) if idx in I else e
        for idx,e in enumerate(l)],sep="")
eof
  • 반복 모듈에서 곱 방법은 입력 반복의 데카르트 곱(이 경우 다중 DNA 시퀀스)을 생성합니다.
  • 우리는 이것을 데카르트 곱의 수에 도달하고 입력 파일에 여전히 데이터가 포함되면 결코 끝나지 않고 처음부터 재활용을 시작하는 무한 반복자로 바꿉니다.

관련 정보