EOF inesperado enquanto procurava o script `" 'correspondente - bash

38

Acabei de escrever um script bash e sempre recebendo esse erro de EOF.

Então, aqui está o meu script (funciona apenas no OS X):

#!/bin/bash

#DEFINITIONS BEGIN
en_sq() {
    echo -e "Enabling smart quotes..."
    defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool true
    status=$(defaults read NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool)
            if [ "$status" = "1" ]
                then
                    echo -e "Success! Smart quotes are now enabled."
                    SUCCESS="TRUE"
            else
                echo -e "Sorry, an error occured. Try again."
            fi
}
di_sq() {
    echo -e "Disabling smart quotes..."
    defaults write NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool false
    status=$(defaults read NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool)
            if [ "$status" = "0" ]
                then
                    echo -e "Success! Smart quotes are now disabled."
                    SUCCESS="TRUE"
            else
                echo -e "Sorry, an error occured. Try again."
            fi
}
en_sd() {
    echo -e "Enabling smart dashes..."
    defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool true
    status=$(defaults read NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool)
            if [ "$status" = "1" ]
                then
                    echo -e "Success! Smart dashes are now enabled."
                    SUCCESS="TRUE"
            else
                echo -e "Sorry, an error occured. Try again."
            fi
}
di_sd() {
    echo -e "Enabling smart dashes..."
    defaults write NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool false
    status=$(defaults read NSGlobalDomain NSAutomaticDashSubstitutionEnabled -bool)
            if [ "$status" = "0" ]
                then
                    echo -e "Success! Smart dashes are now disabled."
                    SUCCESS="TRUE"
            else
                echo -e "Sorry, an error occured. Try again."
            fi
}
#DEFINITIONS END
#---------------

#BEGIN OF CODE with properties
#This is only terminated if the user entered properties (eg ./sqd.sh 1 1)
if [ "$1" = "1" ]
    then
        en_sq
    elif [ "$1" = "0" ]
        then
            di_sq
fi

if [ "$2" = "1" ]
    then
        en_sd
        #exit 0 if both, $1 and $2 are correct entered and processed.
        exit 0
    elif [ "$1" = "0" ]
        then
            di_sd
            #exit 0 if both, $1 and $2 are correct entered and processed.
            exit 0
fi
#END OF CODE with properties
#---------------------------


#BEGIN OF CODE without properties
#This is terminated if the user didn't enter two properties
echo -e "\n\n\n\n\nINFO: You can use this command as following: $0 x y, while x and y can be either 0 for false or 1 for true."
echo -e "x is for the smart quotes, y for the smart dashes."
sleep 1
echo -e " \n Reading preferences...\n"
status=$(defaults read NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool)
if [ "$status" = "1" ]
    then
        echo -e "Smart quotes are enabled."
    elif [ "$status" = "0" ]
    then
        echo -e "Smart quotes are disabled."

    else
        echo -e "Sorry, an error occured. You have to run this on OS X""
fi

status=$(defaults read NSGlobalDomain NSAutomaticQuoteSubstitutionEnabled -bool)
if [ "$status" = "1" ]
    then
        echo -e "Smart dashes are enabled."
    elif [ "$status" = "0" ]
    then
        echo -e "Smart dashes are disabled."

    else
        echo -e "Sorry, an error occured. You have to run this on OS X!"
fi

sleep 3
echo -e "\n\n You can now enable or disable smart quotes."

until [ "$SUCCESS" = "TRUE" ]
do
echo -e "Enter e for enable or d for disable:"
read sq

if [ "$sq" = "e" ]
    then
        en_sq
    elif [ "$sq" = "d" ]
        then
            di_sq
    else
        echo -e "\n\n ERROR! Please enter e for enable or d for disable!"
fi
done
SUCCESS="FALSE"

echo -e "\n\n You can now enable or disable smart dashes."

until [ "$SUCCESS" = "TRUE" ]
do
echo -e "Enter e for enable or d for disable:"
read sq

if [ "$sd" = "e" ]
    then
        en_sd
    elif [ "$sd" = "d" ]
        then
            di_sd
    else
        echo -e "\n\n ERROR! Please enter e for enable or d for disable!"
fi
done

E aqui está o meu erro:

./coding.sh: line 144: unexpected EOF while looking for matching `"'
./coding.sh: line 147: syntax error: unexpected end of file
SimMac
fonte

Respostas:

32

Você pode ver o seu problema se apenas olhar para a sua pergunta. Observe como o realce da sintaxe é estragado após a linha 95:

echo -e "Sorry, an error occurred. You have to run this on OS X""

Como a mensagem de erro informa, você tem um número incomparável ". Basta remover o extra "da linha acima e você deve ficar bem:

echo -e "Sorry, an error occurred. You have to run this on OS X"
terdon
fonte
1
Estranhamente, eu tive o mesmo problema e foi porque eu tinha uma sudo echo ""linha .. Remover as 2 aspas duplas, sair sudo echofaz com que funcione perfeitamente.
vinzee
@vinzee por que você nunca correr echocom sudo? Dito isto, o que você descreve não faz muito sentido, deve ter havido algo mais acontecendo.
terdon
Eu faço isso sudo echoporque o script precisará sudomais tarde nos comandos, mas quero que o usuário insira sua senha desde o início, para que o script não precise mais de sua entrada por alguns minutos. E para o bug, eu tive o mesmo erro como visto aqui, mas foi resolvido removendo as 2 aspas duplas. Nada mais aconteceu ..
vinzee
1
@vinzee você pode querer ler Como executo um comando 'sudo' dentro de um script? . Quanto às citações, deve ter havido algo mais. Talvez você tenha um caractere não imprimível após as aspas que foram excluídas com eles, por exemplo. Ou talvez você tenha duas aspas simples e, em seguida, uma dupla ( echo ''") ou algo assim, mas tinha que haver alguma coisa, pois echo ""está bem.
terdon
Obrigado pelo link, você está certo. Correr sudo echoparecia um pouco estranho .. E tentarei novamente na minha instalação do Linux hoje à noite e voltarei a comentar aqui os resultados.
vinzee
4

Esse erro pode ser difícil de rastrear em situações reais. Aqui eu forneço uma solução para a situação do mundo real. Vou usar meu script como exemplo.

Eu atualizei meu script de shell. Ao executá-lo, recebi a seguinte mensagem de erro:

/somepath/bin/myshellscript: line 1508: unexpected EOF while looking for matching `"'
/somepath/bin/myshellscript: line 1520: syntax error: unexpected end of file

line 1508 elif [ "$project" ]; then

Esta é a última linha que possui um par de aspas duplas.

Normalmente, verifico meu script de shell toda vez que o modifico. Dessa vez, esperei um dia e esqueci onde havia feito as modificações. O problema aconteceu em qualquer lugar antes desta linha (1508). O problema é que até eu comentei a linha 1508

#elif [ "$project" ]; then

o carrasco ainda disse que a linha 1508 tem problemas.

Em seguida, fiz uma cópia do script shell original. Excluindo um monte de código da parte inferior. Valide meu código com o seguinte comando

bash -n mysbashscript

mybashscript: line 515: unexpected EOF while looking for matching `"'
mybashscript: line 561: syntax error: unexpected end of file

Agora, meu arquivo tem 1/3 do tamanho original. Vi imediatamente o problema:

497 prepare_alignment() {
498     local projdir=${1:?"did not give project directory"}
499     local samp=${2:?"did not give sample name"}
500     local merged=${3:?"must give merged bam file name} # here is the problem

Por alguma razão, o "interno {} incomparável não é capturado pelo analisador de shell. É aqui que o analisador de shell pode ser melhorado ainda mais.

O algoritmo mais rápido para encontrar o problema é excluir metade do seu código da parte inferior, se o erro de sintaxe desaparecer, será nesta metade. Se o erro de sintaxe ainda estiver lá, o problema estará na metade superior.

Se houver um problema na metade posterior, desfaça a exclusão. Repita esse processo. Você pode diminuir para um tamanho menor para encontrar a fonte do problema.

Ao excluir o código, você deve excluir uma seção inteira do código. Por exemplo, toda a função.

Você pode usar bash -n scriptname ou apenas executar diretamente o script. Ambos devem funcionar.

Kemin Zhou
fonte
1
"Por alguma razão, o inigualável" dentro {} não é capturado pelo analisador de shell. "Isso ocorre porque, sintaticamente, é correspondido, na linha 1508? seqüência de caracteres é aberta em 1508, que nunca fica fechada.
philh 08/08
Não investiguei o comportamento de cotação do bash. O Bash pode ter uma citação com várias linhas "line1 \ nline2". Lembro que no shell você faz uma citação com várias linhas com << ENDMARK. Possivelmente agora você pode usar diretamente aspas duplas para citar várias linhas. Esse recurso torna a depuração muito difícil.
Kemin Zhou