Shourya Shikhar Asked: 2021-10-25 09:58:12 +0800 CST2021-10-25 09:58:12 +0800 CST 2021-10-25 09:58:12 +0800 CST 为什么在尝试循环用户输入的次数时会得到意外的输出?[复制] 772 我正在编写这个 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} 在这里,我想从用户那里获取限制,然后运行循环。 bash shell 2 个回答 Voted Best Answer user422875 2021-10-25T10:07:11+08:002021-10-25T10:07:11+08:00 来自man bash: 展开顺序为:大括号展开;波浪号扩展、参数和变量扩展、算术扩展和命令替换(以从左到右的方式完成);分词;和路径名扩展。 正如您所看到的,大括号扩展是第一个,所以显然它在您的问题中被跳过了。我会改用不同的循环。 Stéphane Chazelas 2021-10-25T11:02:13+08:002021-10-25T11:02:13+08:00 虽然已经指出了大括号扩展的问题,但我将仅评论: (我相信 declare -i N 使 N 成为整数) 我会回答,是的,确实如此,这是一个问题,因为它使其成为命令注入漏洞。使用该整数属性集,无论何时为变量分配一个值,该值都会被解释为算术表达式。 如果用户a[$(reboot)]在该read提示下输入,例如,这将导致重新启动尝试。 这是,的一个普遍问题bash,每当计算算术表达式时。即使使用ksh93 样式的形式(带或不带)也会成为问题,因为 的内容仍然在该算术上下文中进行评估。zshkshfor (( i = 1; i <= N; i++ ))declare -i NN 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's[仍将操作数-lt视为算术表达式,因此仍会引入命令注入漏洞。不要用[[ $i -lt $N ]]or (( i < N ))in bash//里面也有问题zsh。ksh 或者您可以使用awk/perl或任何适当的编程语言来执行循环,或者您可以首先清理输入。
来自
man bash
:正如您所看到的,大括号扩展是第一个,所以显然它在您的问题中被跳过了。我会改用不同的循环。
虽然已经指出了大括号扩展的问题,但我将仅评论:
我会回答,是的,确实如此,这是一个问题,因为它使其成为命令注入漏洞。使用该整数属性集,无论何时为变量分配一个值,该值都会被解释为算术表达式。
如果用户
a[$(reboot)]
在该read
提示下输入,例如,这将导致重新启动尝试。这是,的一个普遍问题
bash
,每当计算算术表达式时。即使使用ksh93 样式的形式(带或不带)也会成为问题,因为 的内容仍然在该算术上下文中进行评估。zsh
ksh
for (( i = 1; i <= N; i++ ))
declare -i N
N
for i in {1..$N}
declare -i N
在 ksh、zsh 或yash -o braceexpand
(会在乱码上循环但不会引入命令注入漏洞)中会很好(没有),或者如果sh
您的sh
实现不基于ksh
.ksh
's[
仍将操作数-lt
视为算术表达式,因此仍会引入命令注入漏洞。不要用[[ $i -lt $N ]]
or(( i < N ))
inbash
//里面也有问题zsh
。ksh
或者您可以使用
awk
/perl
或任何适当的编程语言来执行循环,或者您可以首先清理输入。