shell - shell - 为(已验证的)提供的数字或数字范围迭代循环
问题描述
我需要接受用户的输入(即“读取”)。
此输入可以是单个正数或一个数字范围(格式为 XY )。
然后我需要验证这个输入并在数字范围内执行一个迭代循环(或者在只有 X 的情况下只执行一次)。
例子:
1) 用户提供:“8”或“8-”循环仅运行一次,提供数字 8
2)用户供应:“13-22”
循环运行 11 次(13 到 22),引用数字 13。
3)用户供应:“22-13”
可能应该表现得像上面的#2......但我愿意接受其他干净的方法来验证输入。
到目前为止,我已经完成了以下工作,这对于我所要求的内容来说不是很干净、完整,甚至 100% 正确 - 但它显示了我所追求的努力和想法:
echo "line?"; read -r deleteline
case "$deleteline" in
''|*[!0-9\-]*) echo "not a number";;
[1-9]|[1-9][0-9]*);;
esac
deleteline_lb=$(echo $deleteline|awk -F "-" '{print $1}')
deleteline_ub=$(echo $deleteline|awk -F "-" '{print $2}')
if [ ! $deleteline_lb = "" ] && [ ! "$deleteline_ub" = "" ]; then
delete_line_count=1
delete_line_count=$(expr $deleteline_ub - $deleteline_lb)
if [ $delete_line_count -le 0 ]; then
delete_line_count=1
fi
fi
i=1; while [ $i -le $delete_line_count ]; do
echo $deleteline_lb $i
i=$(($i + 1))
done
这需要在 sh 中运行,seq
不支持之类的东西 - 所以坚持使用符合 posix 的方法......
为了澄清,我希望执行以下操作(伪代码):1)接受来自用户的输入 2)验证输入是否采用“#”或“#-#”(范围)的形式。3)根据正确/不正确的输入执行选择的(任意)代码路径。4)如果给定单个#,则将其存储到变量以执行未来的操作。5) 如果给定范围,则将两个数字都存储在变量中,以便能够对较低的 # 到较高的数字执行操作。更具体地说,它将是“(较高的#)-(较低的#)+ 1”。因此,如果范围是 12-17,那么我们需要对 12、6x 执行操作。(17 - 12 + 1)。IOW,12-17 包括在内。6) 还需要一种轻松表示数据集是范围还是单个数字的方法,以便可以轻松地分支每个的代码路径。
感谢您的帮助!
更新:
使用我的基本代码,我重新编写了它(朋友的一些意见),基本上想出了这个:
while true;do
printf "\\delete lines? [e=Exit] ";read -r deleteline
case "$deleteline" in
[Ee]) break;;
*)
echo "$deleteline" | egrep -q '^[[:digit:]-]*$'
if [ $? -ne 0 ]; then
printf "\\n input is not a number.\\n"
else
delete_range_start=`echo $deleteline|awk -F "-" '{print $1}'`
delete_range_end=`echo $deleteline|awk -F "-" '{print $2}'`
if [ $delete_range_end -lt $delete_range_start ]; then
printf "\\n upper range must be higher than lower range.\\n"
else
if [ "$delete_range_end" = "" ]; then
delete_range_end=$delete_range_start
elif [ $delete_range_end -gt $lineNumbers ]; then
printf "\\Setting range to last entry\\n"
fi
break
fi
fi
;;
esac
done
deleteline=$delete_range_start
deleteloop=`expr $delete_range_end - $delete_range_start + 1`
i=1
while [ $i -le $deleteloop ]; do
# Insert all processing code in here
i=`expr $i + 1`
done
解决方案
如果你有一个 posix 兼容的 awk,试试这个:
echo "$userInput" | awk -F- '
($1+0==$1&&$2+0==$2){
for(i=$1;($1<$2?i<=$2:i>=$2);)
print ($1<$2?i++:i--);
next
}
$1+0==$1{
print $1;
next
}
$2+0==$2{
print $2;
next
}
($1+0!=$1&&$2+0!=$2){
exit 1
}'
该脚本检查 2 个字段(用 分隔-
)是否为数字。如果是这样,它将以升序或降序方式打印这些数字,具体取决于第一个数字是大于还是小于第二个数字。
如果只有一个输入,脚本只会打印它。
如果所有字段都不是数字,则以非零值退出。
该脚本可以是这样的 shell 脚本的验证步骤:
$ cat test.sh
#!/bin/sh
echo -n "range: "
read -r range
validated_input=$(echo "$range" | awk -F- '($1+0==$1&&$2+0==$2){for(i=$1;($1<$2?i<=$2:i>=$2);)print ($1<$2?i++:i--);next}$1+0==$1{print $1;next}$2+0==$2{print $2;next}($1+0!=$1&&$2+0!=$2){exit 1}')
if [ $? -ne 0 ]; then
echo "Incorrect range" >&2
fi
for i in $validated_input; do
echo "$i"
done
例子:
$ ./test.sh
range: 10-6
10
9
8
7
6
$ ./test.sh
range: 8-
8
$ ./test.sh
range: hello
Incorrect range
推荐阅读
- javascript - 在 Chrome 扩展程序中配置代理的这些范围之间有什么区别?
- python - 如何使用 Python Flask jinja2 显示链接图像?
- terraform - 是否可以通过命令行为 Terraform 目标模块传递变量?
- reactjs - 配置 apache 到服务器静态 reactjs 构建后出现 400 错误请求
- google-analytics - 过滤一天中的时间,以便我在 Google Analytics 中使用正则表达式获得接下来的 48 小时
- vba - VBA动态添加选项按钮到用户窗体
- sql - 如何修复子查询运行时间过长?
- google-play-console - 无权使用谷歌内部应用共享
- saml-2.0 - SAMLResponse 断言后 Spinnaker 注销用户不再有效
- azure - 图形 api url 将成员添加到 azure 活动目录安全组