Erro de sintaxe próximo ao token inesperado 'fi'

14

Eu não quero necessariamente a resposta, mas se alguém puder me indicar alguma literatura ou exemplos. Eu gostaria de descobrir isso.

Quando executo o script, recebo um erro:

Syntax error near unexpected token fi

Eu deduzi que meu problema está na declaração if fazendo meus comentários de declarações if e adicionando echo "$NAME" , que exibe os nomes no /etc/ .

Quando faço alterações, remova o # de if e fi e adicione # a wc -c "$NAME" , recebo o erro de sintaxe que listei acima. Eu adicionei ; entre ] então. Também movi then para a próxima linha sem resolução.

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

     if [ -r "$NAME" -af "$NAME" ] then
          wc -c "$NAME"
     fi
done
    
por Christina A Guzman 30.11.2017 / 22:11

3 respostas

45

Palavras-chave como if , then , else , fi , for , case e assim por diante precisam estar em um local onde o shell espera um nome de comando. Caso contrário, eles são tratados como palavras comuns. Por exemplo,

echo if

imprime apenas if , ele não inicia uma instrução condicional.

Assim, na linha

if [ -r "$NAME" -af "$NAME" ] then

a palavra then é um argumento do comando [ (do qual se queixaria se alguma vez fosse executado). O shell continua procurando pelo then e localiza um fi na posição de comando. Como há um if que ainda está procurando por seu then , o fi é inesperado, há um erro de sintaxe.

Você precisa colocar um terminador de comando antes de then para que seja reconhecido como uma palavra-chave. O terminador de comando mais comum é uma quebra de linha, mas antes de then , é comum usar um ponto-e-vírgula (que tem exatamente o mesmo significado que uma quebra de linha).

if [ -r "$NAME" -af "$NAME" ]; then

ou

if [ -r "$NAME" -af "$NAME" ]
then

Depois de corrigir isso, você receberá outro erro do comando [ porque não entende -af . Você supostamente quis dizer

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

Embora os comandos de teste pareçam opções, você não pode agrupá-los dessa maneira. Eles são operadores do comando [ e precisam ser cada um uma palavra separada (como [ e ] ).

A propósito, embora [ -r "$NAME" -a -f "$NAME" ] funcione, recomendo escrever

[ -r "$NAME" ] && [ -f "$NAME" ]

ou

[[ -r $NAME && -f $NAME ]]

É melhor manter [ … ] condicionais simples porque o comando [ não consegue distinguir facilmente operadores de operando. Se $NAME se parece com um operador e aparece em uma posição onde o operador é válido, ele pode ser analisado como um operador. Isso não acontecerá nos casos simples vistos nesta resposta, mas casos mais complexos podem ser arriscados. Escrever isso com chamadas separadas para [ e usar os operadores lógicos do shell evita esse problema.

A segunda sintaxe usa a construção condicional [[ … ]] que existe no bash (e ksh e zsh, mas não sh simples). Essa construção é sintaxe especial, enquanto [ é analisada como qualquer outro comando, portanto, é possível usar coisas como && dentro e você não precisa citar variáveis, exceto em argumentos para alguns operadores de string ( = , == , != , =~ ) (consulte Quando é necessário fazer uma dupla citação? para detalhes).

    
por 30.11.2017 / 23:07
9

Veja o que mudou da seguinte forma

if [ -r "$NAME" -a -f "$NAME" ]; then
#               ^^^^^          ^
     wc -c "$NAME"
fi

Se você quiser remover todos os comandos no bloco, precisará pelo menos adicionar dois pontos, como

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

ou uma versão de linha

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

    
por 30.11.2017 / 22:29
1

Outros já apontaram, mas se você está procurando uma referência oficial, então RTM

if list; then list; [ elif list; then list; ] ... [ else list;] fi

The if list is executed. If its exit status is zero, the then list is executed. Otherwise, each elif list is executed in turn, and if its exit status is zero, the corresponding thenlist is executed and the command completes. Otherwise, the else list is executed, if present. The exit status is the exit status of the last command executed, or zero if no condition tested true.

Você está perdendo o ;

A sintaxe de list é descrita em man test

    
por 01.12.2017 / 23:10

Tags