脚本是:
#!/bin/bash
# Dynamic Menu Function
createmenu () {
select selected_option; do # in "$@" is the default
if [ 1 -le "$REPLY" ] && [ "$REPLY" -le $(($#)) ]; then
break;
else
echo "Please make a vaild selection (1-$#)."
fi
done
}
declare -a drives=();
# Load Menu by Line of Returned Command
mapfile -t drives < <(lsblk --nodeps -o name,serial,size | grep "sd");
# Display Menu and Prompt for Input
echo "Available Drives (Please select one):";
createmenu "${drives[@]}"
# Split Selected Option into Array and Display
drive=($(echo "${selected_option}"));
echo "Drive Id: ${drive[0]}";
echo "Serial Number: ${drive[1]}";
旧系统没有mapfile
或readarray
所以我需要将该行转换为可以将lsblk
输出的每一行读入数组的替代方案。
创建数组的问题是:
mapfile -t drives < <(lsblk --nodeps -o name,serial,size | grep "sd");
答案 0 :(得分:5)
您可以循环输入并附加到数组:
$ while IFS= read -r line; do arr+=("$line"); done < <(printf '%d\n' {0..5})
$ declare -p arr
declare -a arr='([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5")'
或者,就您的具体情况而言:
while IFS= read -r line; do
drives+=("$line")
done < <(lsblk --nodeps -o name,serial,size | grep "sd")
请参阅BashFAQ/001,了解为什么IFS= read -r
是一个好主意的绝佳解释:它确保空格是守恒的,并且不会解释反斜杠序列。
答案 1 :(得分:0)
这是我前一段时间想出的解决方案。这样会更好,因为它为不支持mapfile / readarray的Bash的较旧版本提供了替代功能。
server
您不必一次更改代码。就是这样!
if ! type -t readarray >/dev/null; then
# Very minimal readarray implementation using read. Does NOT work with lines that contain double-quotes due to eval()
readarray() {
local cmd opt t v=MAPFILE
while [ -n "$1" ]; do
case "$1" in
-h|--help) echo "minimal substitute readarray for older bash"; exit; ;;
-r) shift; opt="$opt -r"; ;;
-t) shift; t=1; ;;
-u)
shift;
if [ -n "$1" ]; then
opt="$opt -u $1";
shift
fi
;;
*)
if [[ "$1" =~ ^[A-Za-z_]+$ ]]; then
v="$1"
shift
else
echo -en "${C_BOLD}${C_RED}Error: ${C_RESET}Unknown option: '$1'\n" 1>&2
exit
fi
;;
esac
done
cmd="read $opt"
eval "$v=()"
while IFS= eval "$cmd line"; do
line=$(echo "$line" | sed -e "s#\([\"\`]\)#\\\\\1#g" )
eval "${v}+=(\"$line\")"
done
}
fi