为什么我在尝试循环用户输入的次数时会得到意外的输出?

为什么我在尝试循环用户输入的次数时会得到意外的输出?

我正在编写这个 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这是,zshksh计算算术表达式时的一个普遍问题。即使使用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 ))bashzshksh

或者您可以使用awk/perl或任何适当的编程语言来执行循环,或者您可以首先清理输入。

相关内容