意外标记“fi”附近的语法错误

Chr*_*man 26 bash

我不一定想要答案,但如果有人可以向我指出一些文献或例子。我想弄清楚。

当我运行脚本时,我收到一个错误:

意外标记附近的语法错误 fi

if通过if发表我的声明评论并添加echo "$NAME"which 在/etc/.

当我进行更改,删除#fromiffiadd #to 时 wc -c "$NAME",我收到上面列出的语法错误。我;]那时之间添加了。我也then没有解决就移到下一行。

#!/bin/bash
for NAME in /etc/*
do

     if [ -r "$NAME" -af "$NAME" ] then
          wc -c "$NAME"
     fi
done
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 54

关键词一样ifthenelsefiforcase等需要在其中壳预期的命令名称的地方。否则,它们将被视为普通单词。例如,

echo if
Run Code Online (Sandbox Code Playgroud)

只是打印if,它不会启动条件指令。

因此,在该行

if [ -r "$NAME" -af "$NAME" ] then
Run Code Online (Sandbox Code Playgroud)

这个词then是命令的一个参数[(如果它运行了它会抱怨)。shell 不断寻找then, 并找到fiin 命令位置。由于有一个if仍在寻找它的then,这fi是意外的,有一个语法错误。

您需要在前面放置一个命令终止符,then以便将其识别为关键字。最常见的命令终止符是换行符,但在 之前then,通常使用分号(其含义与换行符完全相同)。

if [ -r "$NAME" -af "$NAME" ]; then
Run Code Online (Sandbox Code Playgroud)

或者

if [ -r "$NAME" -af "$NAME" ]
then
Run Code Online (Sandbox Code Playgroud)

一旦你解决了这个问题,你会从命令中得到另一个错误 [因为它不理解-af. 你大概是说

if [ -r "$NAME" -a -f "$NAME" ]; then
Run Code Online (Sandbox Code Playgroud)

尽管测试命令看起来像选项,但您不能像这样捆绑它们。他们是运营商[命令的它们每个都需要是一个单独的词(如 do[])。

顺便说一句,虽然 [ -r "$NAME" -a -f "$NAME" ]有效,但我建议要么写

[ -r "$NAME" ] && [ -f "$NAME" ]
Run Code Online (Sandbox Code Playgroud)

或者

[[ -r $NAME && -f $NAME ]]
Run Code Online (Sandbox Code Playgroud)

最好保持[ … ]条件简单,因为[命令不能轻易区分运算符和操作数。如果$NAME看起来像一个运算符并且出现在该运算符有效的位置,则可以将其解析为运算符。在此答案中看到的简单情况下不会发生这种情况,但更复杂的情况可能会有风险。通过单独调用[和使用 shell 的逻辑运算符来编写它可以避免这个问题。

第二种语法使用[[ … ]]bash 中存在的条件构造(以及 ksh 和 zsh,但不是普通的 sh)。此构造是特殊语法,而[像任何其他命令一样被解析,因此您可以使用诸如&&inside 之类的东西,除了某些字符串运算符 ( =, ==, !=, =~) 的参数外,您不需要引用变量(请参阅何时需要双引号) ?详情)。


Bru*_*uce 12

看看有什么变化如下

if [ -r "$NAME" -a -f "$NAME" ] ; 然后
#^^^^^^ ^
     wc -c "$NAME"
菲

如果要删除 if 块中的所有命令,则至少需要在其中添加一个冒号,例如

if [ -r "$NAME" -a -f "$NAME" ]; then
    :
fi
Run Code Online (Sandbox Code Playgroud)

或单行版本

if [ -r "$NAME" -a -f "$NAME" ]; then :; fi