Bash - 連想配列で宣言された変数にキー値を格納する

Bash - 連想配列で宣言された変数にキー値を格納する

私は、ファイル(ビデオ)の名前とその継続時間を含む連想配列を bash で作成しようとしています。コードは次のとおりです。

#!/bin/sh

shopt -s nullglob
movie=(*.mp4)

declare -A MYMAP[$filename]=${duration}

total=${#movie[*]}

for (( i=0; i<=$(( $total -1 )); i++ ))
do

MYMAP[duration]=10
MYMAP[filename]=${movie[i]}
echo "${MYMAP[@]}"
echo "${!MYMAP[@]}"

done

echo "${#MYMAP[@]}"

ファイル名を渡してキー変数に保存し、期間を値変数に保存します。期間は実際には ffprobe を通じて照会されますが、値が変数に正しく渡されていないため、この時点では重要ではありません。

結果は次のとおりです:

$ sh test2.sh
test2.sh: line 6: MYMAP[]: bad array subscript
10 File_01.mp4
duration filename
10 File_02.mp4
duration filename
10 File_03.mp4
duration filename
10 File_04.mp4
duration filename
10 File_05.mp4
duration filename
2

期間とファイル名は両方とも値に入っているようで、キーは変数名だけを出力しているようです。また、配列を次のように宣言すると:

declare -A MYMAP=[$filename]=${duration}

警告は削除されますが、依然としてゴミが出力されます。

答え1

連想配列は、値を取得するために文字列をインデックスとして使用します。これは、整数ではなく文字列を使用して内容を指定する、通常の配列と同じように機能します。

# Declare the array
declare -A durations

# Two movies
sw1="ANewHope.mp4"
sw2="EmpireStrikesBack.mp4"

# Store values
durations[$sw1]=3600
durations[$sw2]=7200

# Retrieve values
echo ${durations[$sw1]}
echo ${durations[$sw2]}

# The movies
echo ${!durations[@]}

# The durations
echo ${durations[@]}

答え2

私は自分の問題を明確に表現できなかったと思うし、おそらくそれはXY問題。私がやりたかったのは、収集することだったファイル名mp4ファイルとその期間連想配列にキーと値のペアとして格納され、ファイル名キーとして期間価値観として。私は完全に間違った方法でそれに取り組んでいました。

これは、映画のファイル名が読み込まれ、同時にその継続時間が調べられ、一度に保存されるという、合理的な解決策のようです。

これが誰かの役に立つことを願います。

 #!/bin/sh
    
    shopt -s nullglob
    
    declare -A DURATIONARR
    
    while IFS= read -r movie
    do 
    DURATIONARR[$movie]=$(ffprobe "$movie" 2>&1 | grep Duration | sed -e 's/^[[:space:]]*//g' | \
    awk '{print $2}' | tr -d ,)
    done< <(find . -name "*.mp4" -exec basename {} \;)
    
    printf "%s\n" "${!DURATIONARR[@]}" "${DURATIONARR[@]}" | pr -2t
    
    unset DURATIONARR

関連情報