-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

おすすめ記事