Shell脚本技术问询:如何实现指定数值范围内的完全数检测与输出
Hey there! Nice work getting the single perfect number check up and running—let's expand that script to handle a range of numbers, including the until loop approach you're curious about.
First, let's refactor your existing check into a reusable function. This makes the code cleaner and easier to call as we iterate through the range:
# Function to check if a number is perfect is_perfect() { local no=$1 # The number to check local i=1 local ans=0 local half=$((no / 2)) # Calculate half once for efficiency # Sum all divisors up to half the number while [ $i -le $half ] do if [ $((no % i)) -eq 0 ] then ans=$((ans + i)) fi i=$((i + 1)) done # Return true (0) if number equals sum of divisors, false (1) otherwise [ $no -eq $ans ] }
Next, we'll add logic to get the range input from the user:
# Get range from user echo "Enter the start of the range:" read start echo "Enter the end of the range:" read end
Option 1: Using a for loop (intuitive for ranges)
This is the most straightforward way to iterate through a range in bash:
echo -e "\nPerfect numbers between $start and $end (using for loop):" for (( num=start; num<=end; num++ )) do if is_perfect $num then echo $num fi done
Option 2: Using an until loop (as you wanted to explore)
The until loop runs until a condition becomes true. Here's how to use it to traverse the range:
echo -e "\nPerfect numbers between $start and $end (using until loop):" num=$start # Initialize counter to start of range # Loop until num exceeds the end of the range until [ $num -gt $end ] do if is_perfect $num then echo $num fi num=$((num + 1)) # Increment counter done
Quick notes on improvements:
- I replaced
exprwith bash arithmetic expansion ($((...))) because it's faster and more readable—no need for subshells here. - Using
localvariables in the function keeps them isolated from the rest of the script, preventing unexpected side effects. - The
is_perfectfunction returns an exit code (0 for true, 1 for false), which works seamlessly with bash'sifstatements.
Putting it all together, your full script would look like this:
#!/bin/bash # Function to check if a number is perfect is_perfect() { local no=$1 local i=1 local ans=0 local half=$((no / 2)) while [ $i -le $half ] do if [ $((no % i)) -eq 0 ] then ans=$((ans + i)) fi i=$((i + 1)) done [ $no -eq $ans ] } # Get range input echo "Enter the start of the range:" read start echo "Enter the end of the range:" read end # Check with for loop echo -e "\nPerfect numbers between $start and $end (for loop):" for (( num=start; num<=end; num++ )) do is_perfect $num && echo $num done # Check with until loop echo -e "\nPerfect numbers between $start and $end (until loop):" num=$start until [ $num -gt $end ] do is_perfect $num && echo $num num=$((num + 1)) done
Just save this as perfect_numbers.sh, make it executable with chmod +x perfect_numbers.sh, and run it—you'll be able to input a range and see all perfect numbers within it!
内容的提问来源于stack exchange,提问作者Diksha Nasa

