好的,所以我已经在这里工作了几天,我刚接触到这个整个bash UNIX系统的新东西,但我正在尝试编写一个脚本,用户输入一个整数,脚本将采用整数和使用作为基数输入的整数打印出三角形并减小直到达到零。一个例子是:
reverse_triangle.bash 4
****
***
**
*
所以这就是我到目前为止所做的事情但是当我跑步时没有任何反应我不知道出了什么问题
#!/bin/bash
input=$1
count=1
for (( i=$input; i>=$count;i-- ))
do
for (( j=1; j>=i; j++ ))
do
echo -n "*"
done
echo
done
exit 0
当我尝试运行它没有任何反应它只是进入下一行。非常感谢帮助:)
答案 0 :(得分:2)
正如我在评论中所说,你的测试是错误的:你需要
for (( j=1; j<=i; j++ ))
而不是
for (( j=1; j>=i; j++ ))
否则,此循环仅在i=1
时执行,并且变为无限循环。
现在,如果你想以另一种方式解决这个问题,那就更好了:
#!/bin/bash
[[ $1 = +([[:digit:]]) ]] || { printf >&2 'Argument must be a number\n'; exit 1; }
number=$((10#$1))
for ((;number>=1;--number)); do
printf -v spn '%*s' "$number"
printf '%s\n' "${spn// /*}"
done
为什么更好?首先,我们检查参数是否真的是一个数字。如果没有这个,您的代码将受到任意代码注入。此外,我们确保使用10#$1
在基数10中理解该数字。否则,像09
这样的参数会引发错误。
我们并不需要为循环提供额外的变量,所提供的参数足够好。现在的诀窍是:打印 n 次模式,一个很酷的方法是将 n 空间存储在printf
的变量中:%*s
将展开到 n 空格,其中 n 是printf
找到的相应参数。
例如:
printf '%s%*s%s\n' hello 42 world
会打印:
hello world
(有42个空格)。
编者注:%*s
一般不会扩展到 n 空格,如上面的输出所示,其中包含 37 空格。
相反,*
映射到42
的参数是s
字段的字段宽度,它映射到跟随参数world
,导致字符串world
左空格填充为42 ;由于world
的字符数为5,因此 37 空格用于填充
要使示例按预期工作,请使用printf '%s%*s%s\n' hello 42 '' world
- 注意42
后面的空字符串参数,确保整个字段由填充组成,即,空格(如果没有参数跟在42
之后,你会得到同样的效果。)
使用printf
&#39; -v
选项,我们可以将printf
格式化的任何字符串存储到变量中;在这里,我们在$number
中存储spn
个空格。最后,我们使用扩展*
替换所有空格${spn// /*}
。
又一种可能性:
#!/bin/bash
[[ $1 = +([[:digit:]]) ]] || { printf >&2 'Argument must be a number\n'; exit 1; }
printf -v s '%*s' $((10#1))
s=${s// /*}
while [[ $s ]]; do
printf '%s\n' "$s"
s=${s%?}
done
这次我们使用前面的技术构造包含一堆s
(用户给出的数字)的变量*
。然后我们有一个while
循环,循环而s
非空。在每次迭代时,我们会打印s
的内容,然后移除包含${s%?}
的扩展s
的字符,删除{{1}}的最后一个字符。
答案 1 :(得分:0)
以gniourf_gniourf's helpful answer:
为基础以下更简单,表现更好:
#!/bin/bash
count=$1 # (... number-validation code omitted for brevity)
# Create the 1st line, composed of $count '*' chars, and store in var. $line.
printf -v line '%.s*' $(seq $count)
# Count from $count down to 1.
while (( count-- )); do
# Print a *substring* of the 1st line based on the current value of $count.
printf "%.${count}s\n" "$line"
done
printf -v line '*%.s' $(seq $count)
是一个打印*
$count
次的技巧,感谢%.s*
为每个提供的参数生成*
,无论参数如何&#39 ;值(感谢%.s
,它有效地忽略了它的参数)。 $(seq $count)
扩展为$count
个参数,从而生成由$count
*
个字符组成的字符串。总体而言,感谢-v line
,它存储在变量$line
。printf "%.${count}s\n" "$line"
打印$line
开头的$count
字符的子字符串。长。