我希望用户在环境select
中从屏幕上的编号列表中获取文件mkinitcpio
busybox
ash
。该列表需要从上到下填充/排序并按列打印,例如:
1) 2017-12-17 3) 2017-12-19 5) 2017-12-21 7) 2017-12-23 9) 2017-12-25
2) 2017-12-18 4) 2017-12-20 6) 2017-12-22 8) 2017-12-24
我正在逐行打印到屏幕printf
。这就是为什么您通常会使用数组。由于busybox
ash
缺乏数组支持,该黑客方法是使用位置参数( 、等)set
来创建穷人的数组。$1=2017-12-17
$2=2017-12-18
现在我设法使用以下方法检索位置参数值:
file=$(eval echo \$$i)
有没有更好的方法来检索第 n 个位置参数在灰?
笔记
- 上面列出的列是一个简化的示例,实际文件名也包含时间戳,例如
2017-12-27-060056
. - Mkinitcpio busybox 1.27.2 编译配置。
答案1
使用:
eval "file=\${$i}"
不需要命令替换,它会在删除尾随换行符时破坏数据,并且效率低下,因为它涉及 fork() 和 pipeline() 并通过该管道在两个进程之间推送数据。
echo
也不应用于任意数据。
另请注意 POSIX sh 语法中对于 9 以上的数字所需的大括号。
如果$i
从用户处读取,您可能需要确保它是从 1 到 1 的十进制整数,并且首先$#
不带前导0
s 或+
s 以避免命令注入漏洞:
valid() { # args: string min max
case $1 in
(*[!0123456789]* | 0* | "" | ??????????*) return 1
esac
[ "$1" -ge "$2" ] && [ "$1" -le "$3" ]
}
until
printf>&2 'Enter number: '
IFS= read -r number
valid "$number" 1 "$#"
do
echo>&2 "Not a valid number. Please try again."
done
eval "file=\${$number}"
答案2
您可以使用平移。这比评估要好。
猫忙.sh
leshift () {
shift "$1"
echo "$1"
}
echo param debut
echo $#
echo $@
for i in "$@" ; do
echo "$i"
done
echo param shift
read a # number from 1 to 5
b=$(leshift "$a" "$@")
echo $b
echo param fin
echo $#
echo $@
for i in "$@" ; do
echo "$i"
done
你就这样称呼它
./busy.sh a b 'c h' d e