하위 문자열 배열을 만드는 방법

하위 문자열 배열을 만드는 방법

문자열인 변수 시퀀스가 ​​있다고 가정해 보겠습니다.

> 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의 크레딧)

관련 정보