在Bash中检索数组元素匹配字符串的索引

时间:2013-11-15 02:17:18

标签: arrays string bash split

钢琴键盘上的每个88键都有声音文件。

p-book:OUT pi$ ls
Piano.ff.A0.aiff    Piano.ff.Bb7.aiff   Piano.ff.Eb1.aiff
Piano.ff.A1.aiff    Piano.ff.C1.aiff    Piano.ff.Eb2.aiff
Piano.ff.A2.aiff    Piano.ff.C2.aiff    Piano.ff.Eb3.aiff
Piano.ff.A3.aiff    Piano.ff.C3.aiff    Piano.ff.Eb4.aiff
Piano.ff.A4.aiff    Piano.ff.C4.aiff    Piano.ff.Eb5.aiff
Piano.ff.A5.aiff    Piano.ff.C5.aiff    Piano.ff.Eb6.aiff
Piano.ff.A6.aiff    Piano.ff.C6.aiff    Piano.ff.Eb7.aiff
Piano.ff.A7.aiff    Piano.ff.C7.aiff    Piano.ff.F1.aiff
Piano.ff.Ab1.aiff   Piano.ff.C8.aiff    Piano.ff.F2.aiff
Piano.ff.Ab2.aiff   Piano.ff.D1.aiff    Piano.ff.F3.aiff
Piano.ff.Ab3.aiff   Piano.ff.D2.aiff    Piano.ff.F4.aiff
Piano.ff.Ab4.aiff   Piano.ff.D3.aiff    Piano.ff.F5.aiff
Piano.ff.Ab5.aiff   Piano.ff.D4.aiff    Piano.ff.F6.aiff
Piano.ff.Ab6.aiff   Piano.ff.D5.aiff    Piano.ff.F7.aiff
Piano.ff.Ab7.aiff   Piano.ff.D6.aiff    Piano.ff.G1.aiff
Piano.ff.B0.aiff    Piano.ff.D7.aiff    Piano.ff.G2.aiff
Piano.ff.B1.aiff    Piano.ff.Db1.aiff   Piano.ff.G3.aiff
Piano.ff.B2.aiff    Piano.ff.Db2.aiff   Piano.ff.G4.aiff
Piano.ff.B3.aiff    Piano.ff.Db3.aiff   Piano.ff.G5.aiff
Piano.ff.B4.aiff    Piano.ff.Db4.aiff   Piano.ff.G6.aiff
Piano.ff.B5.aiff    Piano.ff.Db5.aiff   Piano.ff.G7.aiff
Piano.ff.B6.aiff    Piano.ff.Db6.aiff   Piano.ff.Gb1.aiff
Piano.ff.B7.aiff    Piano.ff.Db7.aiff   Piano.ff.Gb2.aiff
Piano.ff.Bb0.aiff   Piano.ff.E1.aiff    Piano.ff.Gb3.aiff
Piano.ff.Bb1.aiff   Piano.ff.E2.aiff    Piano.ff.Gb4.aiff
Piano.ff.Bb2.aiff   Piano.ff.E3.aiff    Piano.ff.Gb5.aiff
Piano.ff.Bb3.aiff   Piano.ff.E4.aiff    Piano.ff.Gb6.aiff
Piano.ff.Bb4.aiff   Piano.ff.E5.aiff    Piano.ff.Gb7.aiff
Piano.ff.Bb5.aiff   Piano.ff.E6.aiff
Piano.ff.Bb6.aiff   Piano.ff.E7.aiff

我希望将它们重命名为MIDI音符编号:

Piano.ff.A0.aiff  -> 21.aiff
Piano.ff.Bb0.aiff -> 22.aiff
Piano.ff.B0.aiff  -> 23.aiff
Piano.ff.C1.aiff  -> 24.aiff
:

(21是钢琴上最低音符的MIDI编号)

虽然88可能更像是“手工做”的大小,但我很好奇它是否能在几行Bash中实现自动化

如果:

'C'  ~ 0  
'Db' ~ 1  
'D'  ~ 2  
:  
'B'  ~ 11  

然后我可以做:

MidiNote = NumberForPitchclass( pitchclassstring ) + 12 * octave

但Bash是否有这种操作的装置?

1 个答案:

答案 0 :(得分:2)

如果你有bash 4,那么使用关联数组就可以了:

   noteNames=(C Db D Eb E F Gb G Ab A Bb B)
   declare -A noteNumbers
   for (( i=0; i<${#noteNames[@]}; ++i )); do
      noteNumbers[${noteNames[i]}]=$i
   done
   for f in *.aiff; do
      note="${f#Piano.ff.}"
      note="${note%.aiff}"
      name="${note%%[0-9]*}"
      octave="${note#$name}"
      if [ ! -n "${noteNumbers[$name]}" ]; then
         echo >&2 "$0: not renaming $f - note not found"
      else
         let midiNote=${noteNumbers[$name]}+12*octave
         mv "$f" "$midiNote.aiff"
      fi
   done

如果你没有bash 4,你可以通过循环浏览每个文件的注释而不是仅仅开始一次来手动完成:

noteNames=(C Db D Eb E F Gb G Ab A Bb B)
for f in *.aiff; do
   note="${f#Piano.ff.}"
   note="${note%.aiff}"
   name="${note%%[0-9]*}"
   octave="${note#$name}"
   for (( base=0; base<${#noteNames[@]}; ++base )); do
      if [[ "${noteNames[base]}" == $name ]]; then
         break
      fi
   done
   if (( base >= ${#noteNames[@]} )); then
      echo >&2 "$0: not renaming $f - note not found"
   else
      let midiNote=base+12*octave
      mv "$f" "$midiNote.aiff"
   fi
done

然而,这给A0数字10,你说它是21,所以你显然需要在这些数字上加上11。