为什么这个脚本会出现语法错误?

为什么这个脚本会出现语法错误?

运行下面的脚本时,出现错误:

脚本如下:

clear
echo "Enter a num"
read num 
if [ "$num" -ge 0]; then
    f=1
    i=1
    while [ $i -le "$num" ]; do
    f=`expr $f \* $i`
    i=`expr $i+1`
    done
echo "The factorial of $num is $f"
else
echo "Enter positive number"
fi

错误:

Enter a num
5
prog4: 5: [: missing ]
Enter positive number

谢谢

答案1

此脚本中有几个错误。它们都与命令行语法有关,大多数是针对的bash,但有一例是针对单独的expr实用程序的。总结如下:

  • 原始问题与`反引号表达式中的不匹配有关(更一般地说,如何关闭反引号表达式以及 shell 如何处理反引号表达式内的换行符)。
  • 阻止脚本正常运行的其他语法错误与[构造和expr命令中的参数解析有关。

请参阅下文了解详情。

原始EOF in backquote substitution错误

作为Florian Diesch 说(以及Helio 的答案还),最初的问题`第一个反引号命令末尾缺少一个expr ...。然而,这个问题更有趣的地方是为什么你会得到错误信息?这不仅仅是出于好奇心——理解这一点可以帮助您理解这个错误信息以及将来的其他错误信息。

EOF 代表文件结束,这意味着没有更多数据可供读取 - 在这种情况下,bash解释器可以读取文本。EOF 本质上不是错误条件,但当 EOF 是错误时,通常意味着解释器认为您的程序已过早结束 - 它正在预期某些事情,但您的程序中从未发生过。

如果错误消息表明该错误是行结束在反引号替换中,你可能马上就会意识到问题所在(前提是你知道这`叫做反引号,并且命令替换使用反引号构造也称为反引号替换。

为什么bash认为文件结束得太早,而不是线这是因为您实际上可以在反引号表达式中使用换行符(即换行符):

ek@Io:~$ file `which vim
> `
/usr/bin/vim: symbolic link to `/etc/alternatives/vim'

因此,bash 将第一个反引号表达式读为

`expr $f\* $i
i=`

这绝对不是你想要的!

然后你想要作为它看到的第二个反引号表达式的内容外部反引号,并将以下内容视为第二个反引号表达式:

`
done
echo "The factorial of $num is $f"
else
echo "Enter positive number"
fi

这是根本不是你想要的,而且也没有结束反引号,它导致 bash 报告在反引号表达式 ( ) 内已到达文件末尾EOF in backquote substitution

解决方案是不是当然是在脚本的最后添加一个反引号!相反,正如其他人所说的那样,只需在应该在的位置添加缺少的反引号即可。

但请注意,这必须是`,与开头的反引号相同。尽管某些命令行实用程序的输出中显示的奇怪格式可能会给人留下这样的印象:以 开头的内容以`结尾,但事实并非如此。(我注意到,在修复过程'中,我曾一度写过'而不是。)`

关闭[命令:[: missing ]错误

解决第一个问题后,出现prog4: 5: [: missing ]错误。

在 Bash 中,[命令(事实上​​甚至还有单独的[可执行文件,因为与 bash 不同,某些 shell 不提供[内置命令)。它和其第一个参数之间必须有空格。

同样,需要将命令]的结束作为单独的命令行参数传递。也就是说,在结尾和开头的 之前都[必须有空格。][

线路

if [ "$num" -ge 0]; then

因此应改写为:

if [ "$num" -ge 0 ]; then

有关语法的更多详细信息,请参阅和[的输出。help [help test

1+1对阵1 + 1

解决该问题后,您将收到另一个错误,它看起来像这样(可能取决于您正在运行的 bash 版本):

bash: [: 1+1: integer expression expected

问题是expr无法理解1+1的意思是“1 加 1 的和”。它没有将其简化为2,因此[随后检查它的命令没有整数可以求值。

为什么expr实用程序知道1+1应该被解释为一个整数,即 1 和 1? 的总和。这是因为每个数字和算术运算符都必须作为单独的命令行参数传递给expr

ek@Io:~$ expr 1+1
1+1
ek@Io:~$ expr 1 + 1
2

要修复此问题,请重写以下行

    i=`expr $i+1`

改为:

    i=`expr $i + 1`

答案2

在行中

f=`expr $f\* $i

`缺少反引号 ( )。

答案3

我发现你的代码有一些缺陷,下面是一个改进的代码:

clear

read -p "Enter a number: " number
if [[ "$number" =~ ^[0-9]+$ ]]; then
    factorial=1
    for ((i=1;i<=$number; i++)); do
        factorial=$(($factorial * $i))
    done
    echo "The factorial of $number is $factorial"
else
    echo "Enter positive number"
fi

这是编辑列表和说明:

  • 您可以使用read -p "Promt here: " myvar它来代替之前打印的提示。
  • 要检查输入是否为正整数(仅无符号数字),您可以使用这个很棒的 bash 正则表达式:[[ "$number" =~ ^[0-9]+$ ]]检查是否$number仅包含数字。
  • 我缩进代码并使变量名称详细化只是为了易于阅读。
  • 为什么while不使用循环for?它更易读,并缩短了代码。
  • 为什么要调用expr来处理整数?bash有一个惊人的算术扩展

答案4

得到答案了

clear
echo " Enter any number "
read n
temp=$(($n-1))
while [ $temp -gt 1 ]; do
        n=$((n *\ temp))
        temp=$((temp - 1))
done
echo "Factorial of number is $n"

谢谢大家。

相关内容