
Я пытаюсь создать ассоциативный массив в 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[@]}"
Я хочу передать имя файла и сохранить его в переменной key, а длительность — в переменной value. Длительность на самом деле будет запрошена через 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
Длительность и имя файла, похоже, попадают в значение, а key, похоже, просто выводит имена переменных. Также, если я объявлю массив таким образом:
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