Mic*_*ant 38 shell shell-script
我有以下工作代码:
largest_prime=1
for number_under_test in {1..100}
do
is_prime=true
factors=''
for ((divider = 2; divider < number_under_test-1; divider++));
do
remainder=$(($number_under_test % $divider))
[ $remainder == 0 ] && [ is_prime ] && is_prime=false && factors+=$divider' '
done
[ $is_prime == true ] && echo "${number_under_test} is prime!" || echo "${number_under_test} is NOT prime (factors= $factors)" [ $is_prime == true ] && largest_prime=$number_under_test
done
printf "\nLargest Prime= $largest_prime\n"
Run Code Online (Sandbox Code Playgroud)
这段代码运行得很快是 0.194 秒。然而,我发现它&& is_prime= false
有点难以阅读,它看起来(在未经训练的眼睛看来)好像是在测试而不是被设置,这就是它的作用。所以我尝试将其更改&&
为 anif...then
并且这有效 - 但在 14.48 秒时慢了 75 倍。在较高的数字上最为明显。
largest_prime=1
for number_under_test in {1..100}
do
is_prime=true
factors=''
for ((divider = 2; divider < number_under_test-1; divider++));
do
remainder=$(($number_under_test % $divider))
if ([ $remainder == 0 ] && [ $is_prime == true ]); then
is_prime=false
factors+=$divider' '
fi
done
[ $is_prime == true ] && echo "${number_under_test} is prime!" || echo "${number_under_test} is NOT prime (factors= $factors)" [ $is_prime == true ] && largest_prime=$number_under_test
done
printf "\nLargest Prime= $largest_prime\n"
Run Code Online (Sandbox Code Playgroud)
有没有块的清晰度而不是缓慢的?
很棒的反馈!我现在正在使用以下内容。还有别的反馈吗 ?
largest_prime=1
separator=' '
for number_under_test in {1..100}; {
is_prime=true
factors=''
for ((divider = 2; divider < (number_under_test/2)+1; divider++)) {
remainder=$(($number_under_test % $divider))
if [ $remainder == 0 ]; then
is_prime=false
factors+=$divider' '
fi
}
if $is_prime; then
printf "\n${number_under_test} IS prime\n\n"
largest_prime=$number_under_test
else
printf "${number_under_test} is NOT prime, factors are: "
printf "$factors\n"
fi
}
printf "\nLargest Prime= $largest_prime\n"
Run Code Online (Sandbox Code Playgroud)
gle*_*man 67
那是因为你每次都在生成一个子 shell:
if ([ $remainder == 0 ] && [ $is_prime == true ]); then
Run Code Online (Sandbox Code Playgroud)
去掉括号就可以了
if [ $remainder == 0 ] && [ $is_prime == true ]; then
Run Code Online (Sandbox Code Playgroud)
如果你想对命令进行分组,在当前的shell 中有这样的语法:
if { [ $remainder == 0 ] && [ $is_prime == true ]; }; then
Run Code Online (Sandbox Code Playgroud)
(需要尾随分号,请参阅手册)
请注意,[ is_prime ]
这与[ $is_prime == true ]
: 不同,您可以简单地$is_prime
(不带括号)将其编写为调用 bash 内置命令true
或false
命令。
[ is_prime ]
是一个带有一个参数的测试,字符串“is_prime”——当[
给定一个参数时,如果参数非空,则结果为成功,并且该文字字符串始终非空,因此始终为“真”。
为了可读性,我会改变很长的一行
[ $is_prime == true ] && echo "${number_under_test} is prime!" || echo "${number_under_test} is NOT prime (factors= $factors)" [ $is_prime == true ] && largest_prime=$number_under_test
Run Code Online (Sandbox Code Playgroud)
到
if [ $is_prime == true ]; then
echo "${number_under_test} is prime!"
else
echo "${number_under_test} is NOT prime (factors= $factors)"
# removed extraneous [ $is_prime == true ] test that you probably
# didn't notice off the edge of the screen
largest_prime=$number_under_test
fi
Run Code Online (Sandbox Code Playgroud)
不要低估空白以提高清晰度。
我认为你在你的这个功能上工作得太努力了。考虑:
unset num div lprime; set -- "$((lprime=(num=(div=1))))"
while [ "$(( num += ! ( div *= ( div <= num ) ) ))" -eq \
"$(( num *= ( div += 1 ) <= 101 ))" ] && {
set "$(( ! ( num % div ) * div ))" "$@"
shift "$(( ! $1 + ( $1 == 1 ) * $# ))"
}; do [ "$div" -gt "$num" ] && echo "$*"
done
Run Code Online (Sandbox Code Playgroud)
Shell 算法非常有能力自行评估整数条件。它很少需要太多的测试和/或外部作业。这个while
循环很好地复制了您的嵌套循环:
它没有打印那么多,当然,我没有写那么多,但是,例如,将上限设置为 16 而不是上面写的 101 并且......
2
3
4 2
5
6 3 2
7
8 4 2
9 3
10 5 2
11
12 6 4 3 2
13
14 7 2
15 5 3
Run Code Online (Sandbox Code Playgroud)
它肯定在做这项工作。并且它几乎不需要其他东西来近似您的输出:
...
do [ "$div" -eq "$num" ] && shift &&
printf "$num ${1+!}= prime.${1+\t%s\t%s}\n" \
"factors= $*" \
"lprime=$(( lprime = $# ? lprime : num ))"
done
Run Code Online (Sandbox Code Playgroud)
只是这样做而不是echo
...
1 = prime.
2 = prime.
3 = prime.
4 != prime. factors= 2 lprime=3
5 = prime.
6 != prime. factors= 3 2 lprime=5
7 = prime.
8 != prime. factors= 4 2 lprime=7
9 != prime. factors= 3 lprime=7
10 != prime. factors= 5 2 lprime=7
11 = prime.
12 != prime. factors= 6 4 3 2 lprime=11
13 = prime.
14 != prime. factors= 7 2 lprime=13
15 != prime. factors= 5 3 lprime=13
Run Code Online (Sandbox Code Playgroud)
这适用于busybox
. 它非常便携、快速且易于使用。
您的子外壳问题将在大多数外壳中发生,但到目前为止,它在bash
外壳中最为严重。我交替做
( [ "$div" -gt "$num" ] ) && ...
Run Code Online (Sandbox Code Playgroud)
...以及我在上面的几个 shell 中为 101 的上限编写它的方式,并且dash
在 0.017 秒内没有 subshell 和在 1.8 秒内完成了 subshell。busybox
.149 和 2、zsh .149 和 4、bash
.35 和 6,以及ksh93
.149 和 .160。ksh93
不会像其他 shell 那样分叉子 shell。所以也许问题不在于子外壳,而在于外壳。