linux - Bash 将命令解析为二维数组
问题描述
我想制作一个脚本,列出所有可用的 midi 设备并提示用户选择一个,然后再为每个音符分配快捷方式。我设法获得了所有使用aseqdump -l
. 就我而言,这输出:
Port Client name Port name
0:0 System Timer
0:1 System Announce
14:0 Midi Through Midi Through Port-0
20:0 UMC404HD 192k UMC404HD 192k MIDI 1
28:0 Launchpad S Launchpad S MIDI 1
并以我的最低技能制作了一个脚本,在每行之前添加了一个数字,所以它看起来像这样:
Port Client name Port name
1) 0:0 System Timer
2) 0:1 System Announce
3) 14:0 Midi Through Midi Through Port-0
4) 20:0 UMC404HD 192k UMC404HD 192k MIDI 1
5) 28:0 Launchpad S Launchpad S MIDI 1
然后提示用户根据左侧的数字选择设备。所有的乐趣和游戏,但我不知道我怎么能只阅读设备名称。例如,如果用户输入“4”,我希望我的 mDevice 变量等于“UMC404HD 192k”,这样我就可以调用aseqdump -p $(mDevice)
并监控它的活动。
我尝试逐字阅读命令输出,但这似乎没用,因为每个字段中的字数从 1 到 5 甚至更多不等。是否可以将此命令的输入解析为二维数组,其中一维将存储设备?例如,我理想情况下有
mDevicesArray[0] = { "0:0", "System, "Timer"}
mDevicesArray[1] = { "0:1", "System", "Announce"}
...
mDevicesArray[4] = { "28:0", "Launchpad S", "Launchpad S MIDI 1"}
然后使用此数组对设备进行进一步处理。
解决方案
bash 没有二维数组。只要执行速度不是什么大问题,您就可以使用关联数组模拟一个:
$ cat ./tst.sh
#!/bin/env bash
declare -A mDevicesArray
mDevicesSet() {
local rowNr="$1" colNr
shift
for (( colNr=1; colNr<=$#; colNr++ )); do
mDevicesArray["${rowNr},${colNr}"]="${!colNr}"
done
}
mDevicesSet 1 '0:0' 'System' 'Timer'
mDevicesSet 2 '0:1' 'System' 'Announce'
mDevicesSet 3 '14:0' 'Midi Through' 'Midi Through Port-0'
mDevicesSet 4 '20:0' 'UMC404HD 192k' 'UMC404HD 192k MIDI 1'
mDevicesSet 5 '28:0' 'Launchpad S' 'Launchpad S MIDI 1'
printf '%s\n' "${mDevicesArray[4,2]}"
$ ./tst.sh
UMC404HD 192k
否则,还有其他各种解决方法,例如eval
,我不推荐使用它,或者为了简单、稳健和效率,您可以使用mDevicesArray1[1]="0:0"; mDevicesArray2[1]="System"; mDevicesArray3[1]="Timer"
等等,并简单地编写函数来访问数组,就好像它们是 2D 一样,例如:
$ cat tst.sh
#!/bin/bash
mDevicesSet() {
local rowNr="$1"
shift
mDevicesArray1["$rowNr"]="$1"
mDevicesArray2["$rowNr"]="$2"
mDevicesArray3["$rowNr"]="$3"
}
mDevicesGet() {
local rowNr=$1 colNr=$2 val
case $colNr in
1 ) val="${mDevicesArray1[$rowNr]}" ;;
2 ) val="${mDevicesArray2[$rowNr]}" ;;
3 ) val="${mDevicesArray3[$rowNr]}" ;;
esac
printf '%s\n' "$val"
}
mDevicesSet 1 '0:0' 'System' 'Timer'
mDevicesSet 2 '0:1' 'System' 'Announce'
mDevicesSet 3 '14:0' 'Midi Through' 'Midi Through Port-0'
mDevicesSet 4 '20:0' 'UMC404HD 192k' 'UMC404HD 192k MIDI 1'
mDevicesSet 5 '28:0' 'Launchpad S' 'Launchpad S MIDI 1'
printf '%s\n' "$(mDevicesGet 4 2)"
$ ./tst.sh
UMC404HD 192k
与使用关联数组相比,虽然执行速度更快,但索引数组方法的缺点是您拥有硬编码的列数 (3),并且每行必须具有相同的列数,并且更难扩展超过 2 个指数。
推荐阅读
- python-3.x - 在 Databricks 中分解结构
- javascript - 在映射后合并并过滤两个对象
- excel - 使用 xlwings 启动特定版本的 Excel
- pytorch - PyTorch - 如何使用平均 2d 池化作为数据集转换?
- javascript - 数字的 Angular Typescript 接口在表单验证中设置为 null ,然后一元加运算符如果未设置则抛出错误
- command-line - 使用 ImageMagick 加快缩小大型 JPEG 图像的大小
- c - valgrind 仍然可达泄漏的示例
- postgresql - 注册/登录页面在 localhost 中工作,但在 Heroku 上出现应用程序错误 (h12/503)
- c++ - 为什么`iota(0) | take(0)` 不是 C++20 中的模型范围::sized_range?
- single-sign-on - 如何在单点登录 (SSO) 中处理令牌到期?