다른 연관 배열을 기반으로 연관 배열 만들기

다른 연관 배열을 기반으로 연관 배열 만들기

아래와 같이 연관 배열을 만들었습니다. 몇 가지 세부 정보를 제공하기 위해 키는 특정 파일을 참조합니다. 더 큰 스크립트의 컨텍스트에서 이 배열을 사용할 것이기 때문입니다(파일이 포함된 디렉터리는 getopts 매개 변수가 됩니다).

declare -A BAMREADS
echo "BAMREADS array is initialized"

BAMREADS[../data/file1.bam]=33285268
BAMREADS[../data/file2.bam]=28777698
BAMREADS[../data/file3.bam]=22388955

echo ${BAMREADS[@]}  # Output: 22388955 33285268 28777698
echo ${!BAMREADS[@]} # Output: ../data/file1.bam ../data/file2.bam ../data/file3.bam

지금까지 이 배열은 내가 예상한 대로 작동하는 것 같습니다. 이제 이 배열을 기반으로 또 다른 연관 배열을 만들고 싶습니다. 구체적으로 말하면, 두 번째 배열은 첫 번째 배열과 동일한 키를 갖지만 $MIN이라는 변수로 값을 나누고 싶습니다.

다음 전략 중 어느 것이 가장 좋은지 잘 모르겠고 둘 중 어느 것도 제대로 작동하지 않는 것 같습니다.

전략 1:배열을 복사하고 배열을 수정하시겠습니까?

MIN=33285268

declare -A BRAMFRACS
echo "BAMFRACS array is initialized"
BAMFRACS=("${BAMREADS[@]}")

echo ${BAMFRACS[@]}  # Output: 22388955 33285268 28777698
echo ${!BAMFRACS[@]} # Output: 0 1 2

이것은 내가 원하는 열쇠가 아닙니다. 작동하더라도 모든 값에 대해 언급한 작업을 수행해야 합니다.

전략 2: 첫 번째 배열을 반복하면서 두 번째 배열을 구성합니다.

MIN=33285268

declare -A BRAMFRACS
echo "BAMFRACS array is initialized"

for i in $(ls $BAMFILES/*bam)
do
    echo $i
    echo ${BAMREADS[$i]}
    BAMFRACS[$i] = ${BAMREADS[$i]} 
done

echo ${BAMFRACS[@]}
echo ${!BAMFRACS[@]}


#When I run this, I get the following error which I am unsure how to solve:

../data/file1.bam
33285268
script.bash: line 108: BAMFRACS[../data/file1.bam]: No such file or directory
../data/file2.bam
28777698
script.bash: line 108: BAMFRACS[../data/file2.bam]: No such file or directory
../data/file3.bam
22388955
script.bash: line 108: BAMFRACS[../data/file3.bam]: No such file or directory

감사해요

답변1

연관 배열 복사에 대한 보다 일반적인 질문에 대답합니다.

관리자가 4.0에서 자체 연관 배열을 도입했을 때 bashzsh API 대신 ksh93 API를 복사하는 불행한 결정을 내렸습니다.

ksh93/ bash는 연관 배열 설정을 전체적으로 지원하지만 다음과 일치하지 않습니다.

hash=([k1]=v1 [k2]=v2)

통사론. 시간이 지나면 zsh그렇죠

hash=(k1 v1 k2 v2)

( ([k]=v...)ksh93 구문에 대한 지원은 나중에 호환성을 위해 추가되었습니다).

그러나 이는 ksh93 및 bash를 사용하여 임의의 키 및 값 목록에서 해시를 생성하는 것이 매우 까다롭다는 것을 의미합니다.

zsh구문을 사용하면 목록을 키와 값이 교대로 전달되기만 하면 됩니다. 예를 들어 두 개의 연관 배열을 복사하려면 다음을 수행하십시오.

h2=("${(@kv)h1}")

또는 두 개의 열이 있는 CSV에서:

IFS=$'\n,'; h=($(<file.csv))

또는 키와 값의 배열에서:

h=("${(@)keys:^values}")

ksh93/ 구문을 사용할 bash때 키와 값 목록(예: 및 in )으로 확장할 수 있는 "${!h[@]}"and 가 있지만 원하는 구문의 (in) 키와 값으로 확장할 수 있는 연산자는 없습니다 ."${h[@]}""${(@k)h}""${(@v)h}"zsh[key]=valueh=(...)"${(@kv)h}"zsh

루프의 요소를 복사하는 대신 연관 배열을 복사하기 위해 이러한 셸에서 사용할 수 있는 한 가지 방법은 typeset -p.

예를 들어 다음을 사용하여 복사와 동일한 작업을 zsh수행할 수 있습니다.h2=("${(@kv)h1}")h1h2ksh93bash

h1_definition=$(typeset -p h1) &&
  eval "typeset -A h2=${h1_definition#*=}"

bash다음과 같이 단축할 수 있습니다 .

h1_definition=$(typeset -p h1) &&
  typeset -A h2="${h1_definition#*=}"

(ksh93에서와 같이 typeset -A h=valuein의 약어이지만, 시작하고 끝나는 경우 내용은 (참조되거나 일부 확장의 결과인 경우에도) 전달된 것처럼 복합 연관 할당으로 해석됩니다.typeset -A h=([0]=value)bashvalue()eval(

마지막으로 루프를 사용하는 것도 쉽습니다.

for k in "${!h1[@]}"; do h2[$k]=${h1[$k]}; done

답변2

이전 배열에서 새 배열을 만듭니다.

MIN=33285268

declare -A BRAMFRACS
for key in "${!BAMREADS[@]}"; do
    BRAMFRACS[$key]=$(( ${BAMREADS[$key]} / MIN ))
done

코드에 대한 의견:

  • 첫 번째 제안 코드가 복사되었기 때문에 작동하지 않습니다.가치연관 배열에서 새 배열로. 이러한 값은 자동으로 키 0, 1, 2를 가져오지만 원래 키는 복사되지 않습니다. 위에 표시된 대로 키별로 배열을 복사해야 합니다. 이렇게 하면 올바른 키에 원하는 값을 할당할 수 있습니다.

  • =두 번째 제안 코드에는 할당 주위에 공백이 있기 때문에 구문 오류가 있습니다 . 여기서 보고 있는 오류가 발생합니다. "피연산자를 사용하여 실행되는 명령 variable = value"으로 해석됩니다.variable=value

  • 일련의 경로 이름을 반복하려면 다음을 수행하십시오.사용하지 마세요ls. 대신 for pathname in "$BAMFILES"/*bam; do.

  • 변수 확장을 인용해 보세요.

  • 가변 데이터를 출력하는 printf대신 사용을 고려하십시오 .echo

관련된:

답변3

다음 bash는 연관 배열 AA2(설정되지 않을 수 있음)의 값을 다른 연관 배열 AA1(대부분 -A로 선언해야 함)에 할당합니다.

LIST="$(declare -p AA2 2>/dev/null)"
[[ "$LIST" ]] && AA1+=${LIST#*=}
  • declare -p변수 값을 declare명령문으로 에코하는 것은 단어 분할 문제 없이 인터프리터에 직접 전달될 수 있습니다.
  • ${LIST#*=}등호와 그 앞의 모든 것을 제거합니다.
  • 0이 아닌 길이 테스트( 2>/dev/null) 중에 오류( )를 숨기면 AA2 설정을 해제할 수 있습니다.declare[[ "$LIST" ]]
  • AA1 또는 AA2가 연관 배열이 아닌 경우 예기치 않은 결과(오류 아님)가 발생합니다.

답변4

이렇게 하면 트릭을 수행할 수 있습니다(추가 키 값도 추가할 수 있음).

declare -A origDict=( [keya]=value_a [keyb]=value_b [keyc]=value_c )
declare -a newDict=( echo ${origDict[*]} [keynew]=new_value )

관련 정보