我正在编写这个 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
或任何适当的编程语言来执行循环,或者您可以首先清理输入。