문자열인 변수 시퀀스가 있다고 가정해 보겠습니다.
> sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
각 요소가 초기 시퀀스의 3자 하위 문자열인 seq와 같은 배열을 만들고 싶습니다.
echo $seq[1]
echo $seq[2]
echo $seq[n]
다음을 제공합니다:
AAA
GCA
TAG
여기서 n은 배열의 마지막 요소입니다. 누군가 이를 위해 스크립트를 작성할 수 있습니까? 이것은 제가 하려고 하는 유닉스 코드와 C++ 코드의 이상한 혼합입니다. 하지만 모두 유닉스 코드여야 합니다.
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
array_name=(seq) while($i+2<length(sequence)) {
seq[i]=substring(sequence,i,3) i=i+3 }
답변1
다음에서 이 작업을 수행한다고 가정해 보겠습니다 bash
.
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
for (( i = 0; i < ${#sequence}; i += 3 )); do
printf '%s\n' "${sequence:i:3}"
done
이는 한 번에 3개의 염기쌍씩 시퀀스 길이에 걸쳐 반복됩니다. 각 반복마다 세 개의 염기로 구성된 다음 세트를 인쇄합니다.
seq
인쇄하는 대신 배열에 넣으려면 다음을 수행하십시오 .
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
for (( i = 0; i < ${#sequence}; i += 3 )); do
seq+=( "${sequence:i:3}" )
done
이것은 당신에게 배열을 제공합니다 seq
. 개별 배열 요소는 등 으로 사용될 수 있습니다 "${seq[0]}"
."${seq[1]}"
나머지 두 개를 얻으려면독서 상자, 1 또는 2에서 시작하도록 루프를 변경합니다.
답변2
에서는 bash
루프와 인덱싱을 사용하여 긴 문자열을 처리하는 것이 가능합니다.매우속도가 느립니다. 대안으로 read
문자열을 사용하여 배열을 만들 수 있습니다.
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
declare -a seq=( "" )
while read -n 3 -r triple ; do seq+=( "$triple" ); done <<< "$sequence"
declare -p seq
배열은 빈 문자열의 인덱스 0으로 생성되므로 필요에 따라 인덱싱이 1부터 시작됩니다.
작동 방식은 read -n 3
" "를 사용하여 한 번에 세 문자를 변수로 읽어서 triple
배열( +=
) 에 추가하고 <<<
리디렉션을 사용하여 시퀀스를 렌더링하는 것 입니다 stdin
. read
입력이 3의 배수가 아닌 경우를 처리합니다.
(위의 인코딩과 마찬가지로 이는 연속된 문자 시퀀스를 읽는 데 좋습니다. 이는 공백, 이스케이프 문자, 널 바이트 등을 특별히 처리하지 않기 때문에 일반적인 "분할" 루틴이 IFS=""
아닙니다 read
. 입력에서 공백을 제거해야 하는 경우에 사용됩니다 ... <<< ${sequence// /}
.
이는 보다 일반적인 문제의 특별한 경우입니다. Bash에서 문자열을 배열로 분할, 부주의한 프로그래머의 모든 흥미로운 함정에 대해서도 읽을 수 있습니다. )
답변3
문자열에 공백이나 개행 문자가 포함되어 있지 않으면 grep
구분된 문자열을 사용하여 배열을 만들 수 있습니다.
sequence="AAAGCATATGCTAGCCCGTATAGCGATACTAGCTATACGATATATATGATCAATGCCCGTATAG"
seq=( $(printf '%s' "$sequence" | grep -o ... ) )
또는 fold
대신 사용하십시오 grep
:
seq=( $(printf '%s' "$sequence" | fold -b3 ) )
와 비교하면 grep
마지막 문자( G
)도 배열 요소가 됩니다.
노트: 문자열에 가 포함된 경우 *
경우에 따라 문제가 발생할 수 있습니다 . 예를 들어, 현재 작업 디렉토리에 seq=( AT* ATA ATG )
로 시작하는 파일 이름이 있으면 파일 이름으로 확장됩니다. 이를 사용하여 와일드카드를 방지 AT
할 수 있습니다 .set -o noglob
더 나은 선택: readarray
대신 사용 seq=(...)
:
readarray seq < <(printf '%s' "$sequence" | fold -b3 )
(@Kusalananda의 크레딧)