![为什么我在尝试循环用户输入的次数时会得到意外的输出?](https://linux22.com/image/197430/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E5%9C%A8%E5%B0%9D%E8%AF%95%E5%BE%AA%E7%8E%AF%E7%94%A8%E6%88%B7%E8%BE%93%E5%85%A5%E7%9A%84%E6%AC%A1%E6%95%B0%E6%97%B6%E4%BC%9A%E5%BE%97%E5%88%B0%E6%84%8F%E5%A4%96%E7%9A%84%E8%BE%93%E5%87%BA%EF%BC%9F%20.png)
我正在编写这个 bash shell 脚本:
#!/bin/bash
declare -i N
read N
for i in {1..$N}
do
echo "Number: $i"
done
(我相信declare -i N
使N
整数)
但是,在运行此命令时,我得到以下输出:
>vim new.sh
>chmod +x passgen.sh
>./passgen.sh
15
Number: {1..15}
这里我想从用户那里获取限制,然后运行循环。
答案1
从man bash
:
展开的顺序是:大括号展开;波形符扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和路径名扩展。
正如您所看到的,大括号扩展是第一个,所以显然它在您的问题中被跳过。我会使用不同的循环。
答案2
虽然已经指出了大括号扩展的问题,但我只想评论一下:
(我相信声明 -i N 使 N 成为整数)
我会回答,是的,确实如此,这是一个问题,因为它使其成为命令注入漏洞。通过设置该整数属性,每当为变量分配一个值时,该值都会被解释为算术表达式。
如果用户a[$(reboot)]
在该read
提示下输入,则会导致尝试重新启动。
bash
这是,zsh
和ksh
计算算术表达式时的一个普遍问题。即使使用for (( i = 1; i <= N; i++ ))
ksh93 样式的形式(带或不带declare -i N
)也会出现问题,因为 的内容N
仍在该算术上下文中计算。
for i in {1..$N}
declare -i N
在 ksh、zsh 或yash -o braceexpand
(会在乱码上循环但不会引入命令注入漏洞)中会很好(没有),或者您可以使用标准sh
语法,前提是您的sh
实现不是基于ksh
.
#! /bin/sh -
IFS= read -r N
i=1; while [ "$i" -lt "$N" ]; do
printf '%s\n' "Number: $n"
done
ksh
仍然[
将操作数视为-lt
算术表达式,因此仍然会引入命令注入漏洞。//不要在其中使用[[ $i -lt $N ]]
or也有问题。(( i < N ))
bash
zsh
ksh
或者您可以使用awk
/perl
或任何适当的编程语言来执行循环,或者您可以首先清理输入。