-A MYASSOCIATIVERRY를 전 세계적으로 선언하는 방법은 무엇입니까?

-A MYASSOCIATIVERRY를 전 세계적으로 선언하는 방법은 무엇입니까?

이 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

관련 정보