-A MYASSOCIATIVARRY를 전 세계적으로 선언하는 방법은 무엇입니까? [복사]

-A MYASSOCIATIVARRY를 전 세계적으로 선언하는 방법은 무엇입니까? [복사]

이 SO 게시물에 설명된 것과 동일한 문제가 있습니다("콜론이 있는 bash 연관 배열 키 문자열에서 오류가 발생함").https://stackoverflow.com/q/40406187/10639803

해결책은 을 사용하는 것입니다 declare -A. 그러나 사용하자마자 내 연관 배열은 더 이상 전역적이지 않습니다.

어떤 방법이 있나요?declare -A 그리고글로벌인가요?

업데이트: declare -gA여기에 설명된 대로 시도했습니다.https://stackoverflow.com/a/21151984/10639803그러나 어떤 이유로 그것은 나에게 작동하지 않습니다. 연관 배열(해시맵)을 채우는 루프를 종료하자마자 배열이 설정 해제됩니다.

이것은 실제 bash 코드입니다(루프 내부의 echo 명령은 값이 실제로 추출되고 할당되었는지 확인하는 것입니다).

declare -gA HOSTS_START_MAP
find "$TEMP" -type f -name "debug.log*" -exec grep -F "STARTING HOST " {} \; |
while IFS= read -r HOST_START_LINE; do
    if [[ $HOST_START_LINE =~ (.*)(DEBUG)(.*)(STARTING HOST)([ 0-9]*)(.*)(CALCULATION) ]]
    then
        HOST_START_TIME=$(echo "${BASH_REMATCH[1]}" | xargs)
        HOST_NAME=$(echo "${BASH_REMATCH[6]}" | xargs)
        # echo ">$HOST_NAME< ... >$HOST_START_TIME<"
        HOSTS_START_MAP[$HOST_NAME]=$HOST_START_TIME
        # echo $HOST_NAME --- ${HOSTS_START_MAP[$HOST_NAME]}
    fi
done

echo ${#HOSTS_START_MAP[@]}
for MYKEY in "${!HOSTS_START_MAP[@]}"; do echo $MYKEY --- ${HOSTS_START_MAP[@]}; done

답변1

보고 있는 문제는 변수 선언과 관련이 없습니다. 이는 하위 셸에서 변수를 설정하고 해당 값을 상위 셸에서 사용할 수 있을 것으로 예상하기 때문입니다.

코드와 동일한 구조를 사용하지만 더 간단한 예를 사용하여 여기에서 이 효과를 확인할 수 있습니다.

a=""
echo find | while read item; do a="$item"; done
echo "a=$a"

다행히도 bash코드를 다른 형식으로 다시 작성하면 빠른 해결 방법이 있습니다.

a=""
while read item; do a="$item"; done < <( echo find )
echo "a=$a"

실제 코드에서는 처리되지 않은 입력이 수신되었는지 while IFS= read -r item확인하는 데 사용됩니다. item예제를 더 명확하게 하기 위해 안전 장치를 생략했습니다.


이 답변에 대한 의견에서 귀하는 코드의 수정된 버전을 요청했습니다. 테스트할 수 없기 때문에 처음에 여기에 넣는 것을 주저했지만 다음과 같이 보일 것입니다.

#!/bin/bash
#
declare -gA HOSTS_START_MAP
while IFS= read -r HOST_START_LINE; do
    if [[ $HOST_START_LINE =~ (.*)(DEBUG)(.*)(STARTING HOST)([ 0-9]*)(.*)(CALCULATION) ]]
    then
        HOST_START_TIME=$(echo "${BASH_REMATCH[1]}" | xargs)
        HOST_NAME=$(echo "${BASH_REMATCH[6]}" | xargs)
        # echo ">$HOST_NAME< ... >$HOST_START_TIME<"
        HOSTS_START_MAP[$HOST_NAME]=$HOST_START_TIME
        # echo $HOST_NAME --- ${HOSTS_START_MAP[$HOST_NAME]}
    fi
done < <( find "$TEMP" -type f -name "debug.log*" -exec grep -F "STARTING HOST " {} \; )

echo ${#HOSTS_START_MAP[@]}
for MYKEY in "${!HOSTS_START_MAP[@]}"; do echo $MYKEY --- ${HOSTS_START_MAP[@]}; done

관련 정보