我正在尝试编写一个 bash 脚本来自动安装我的软件包。因此,我的想法是读取一个 .csv 文件 (packages.csv),如下所示:
pkg,Description,option
wget,file downloader,on
curl,tool to transfer data from or to a server,on
nano,text editor for Unix-like computing systems,off
emacs,An extensible customizable free/libre text editor — and more,on
为每一列(不带标题)构建一个数组,然后将数组传递给对话框清单。
#!/bin/bash
input="packages.csv"
while IFS=',' read -r col1 col2 col3
do
for a in $col1; do
array_col1+=("$a")
done
for b in $col2; do
array_col2+=("$b")
done
for c in $col3; do
array_col3+=("$c")
done
done < "$input"
array1=("${array_col1[@]:1}")
array2=("${array_col2[@]:1}")
array3=("${array_col3[@]:1}")
let num=${#array2[*]}-1
for i in $(seq 0 $num); do
list[i]=$(echo ${array1[i]} ${array2[i]} ${array3[i]})
done
OPTION=$(dialog --checklist "Choose packages:" \
10 60 4 \
${list[*]})
exitstatus=$?
if [ $exitstatus = 0 ]; then
echo "$OPTION"
else
echo "Cancel"
fi
我确实让它在某个时候工作了,但描述中没有任何空格。在我做了一些更改以包含空格之后,它根本不起作用。我该如何修复它?实际上在我的 .csv 文件中我有 3 列以上,但 bash checklist 需要 3 个参数。是否可以以某种方式将它们包含在清单中?
答案1
#!/bin/bash
input="packages.csv"
while IFS=',' read -r col1 col2 col3 dummy
do
array+=("$col1")
array+=("$col2")
array+=("$col3")
done < <(tail -n +2 "$input")
option=$(dialog --checklist --output-fd 1 "Choose packages:" 10 60 4 "${array[@]}")
exitstatus=$?
if [ $exitstatus = 0 ]; then
echo "$option"
else
echo "Cancel"
fi
主要变化:
tail -n +2 "$input"
去掉标题;dummy
变量允许超过三列(额外的列不重要dialog
);- 用一个
array
变量来构建输入,dialog
而不是用许多不完善的方式传递数据; "${array[@]}"
在这种情况下,将数组作为命令行参数传递的正确方法;--output-fd 1
解释在这个答案中(那里有更好,更强大的解决方案);- 每个小写变量这个答案。
实际上,我的文件中
.csv
有 3 列以上,但 bash checklist 需要 3 个参数。是否可以以某种方式将它们包含在清单中?
为什么?没错,dialog --checklist
希望它们三列三列。保持整洁。我猜也许你需要更多的列来显示你的代码后 dialog
考虑一下:当dialog
成功从第一列返回标识符并且您将它们放在中时$option
,请像这样解析其输出:
for package in $option; do … ; done
(要使其正常工作,第一列packages.csv
不能包含空格等)
这样,您就可以为每个选定的包做一些事情。在这个循环中,您可以根据需要重新读取任意数量的列,但首先grep
要读取正确的行:
IFS=',' read -r col1 col2 col3 col4 col5 col6 dummy < <(grep "^${package}," "$input")
(提示:调查read -a
,参见help read
)。然后,仍然在循环内部,完成其余的工作。