Shell脚本出现expr非整数参数错误,请求排查代码问题
Hey there! Let's break down what's causing that frustrating error in your factorial sum script, and fix it up step by step.
First, let's look at your original code to spot the issues:
num=$1 sum=0; rn=0 less=0; fact=0 while [ $num -gt 0 ] do rn=`expr $num % 10` num=`expr $num / 10` while [ $rn -gt 1 ] do less=`expr %rn - 1` # Here's a big problem! fact=`expr $rn \* less` rn=`expr $rn - 1` done sum=`expr $sum + $fact` done echo $sum
Key Issues Causing the Error
Incorrect Variable Reference
The lineless=expr %rn - 1`` uses%rninstead of$rn. Without the dollar sign,exprtreats%rnas a literal string, not the integer value stored in thernvariable. That's exactly why you're getting the "non-integer argument" error.Uninitialized Factorial Variable
You setfact=0at the start, but factorial calculations start at 1 (e.g., 5! = 5×4×3×2×1). If you start with 0, every factorial result will be 0, and you'll never get the correct sum. Worse, you don't resetfactbetween calculating each digit's factorial—so old values will carry over and mess up subsequent calculations.Overwriting the Outer Loop's Variable
Your inner loop modifiesrn, which is the variable you're using in the outer loop to extract digits fromnum. This will throw off the outer loop's logic, causing it to process digits incorrectly.
Fixed Version of the Script
Here's the corrected code with explanations of each change:
num=$1 sum=0 while [ $num -gt 0 ] do # Extract the last digit of num rn=$(expr $num % 10) # Remove the last digit from num num=$(expr $num / 10) # Reset fact to 1 for each new digit's factorial calculation fact=1 # Use a temp variable to avoid messing with the outer loop's rn temp_rn=$rn while [ $temp_rn -gt 1 ] do # Correctly reference the temp_rn variable with $ less=$(expr $temp_rn - 1) # Multiply current fact by temp_rn to build the factorial fact=$(expr $fact \* $temp_rn) # Decrement the temp variable for the next iteration temp_rn=$less done # Add the calculated factorial to the total sum sum=$(expr $sum + $fact) done echo $sum
What Changed?
- Replaced
%rnwith$temp_rnto properly reference the variable's integer value, eliminating theexprerror. - Added a
temp_rnvariable to handle the factorial calculation, so we don't overwrite thernvalue used in the outer loop. - Reset
fact=1at the start of each digit's factorial calculation to ensure accurate results. - Switched to
$(...)for command substitution (instead of backticks) — it's more readable and less prone to nesting issues, though backticks would still work if you prefer them.
Test this script with a number like 145 (a factorion, where the sum of the factorials of its digits equals the number itself) — it should output 145 as expected!
内容的提问来源于stack exchange,提问作者Richi Dubey

