Shell syntax error near unexpected token

Have you ever seen the message "syntax error near unexpected token" while running one of your Bash scripts? I will show you why it occurs and how to fix it.

Have you ever seen the message “syntax error near unexpected token” while running one of your Bash scripts?

In this guide I will show you why this error occurs and how to fix it.

Why the Bash unexpected token syntax error occurs?

As the error suggests this is a Bash syntax error, in other words it reports bad syntax somewhere in your script or command. There are many things that can go wrong in a Bash script and cause this error. Some common causes are missing spaces next to commands and lack of escaping for characters that have a special meaning for the Bash shell.

Finding the syntax error reported when you execute your script is not always easy. This process often requires you to change and retest your script multiple times.

To make your life easier I have analysed different scenarios in which this syntax error can occur. For every scenario I will show you the script or command with the error and the fix you need to apply to solve the problem.

Let’s get started!

One Approach to Fix Them All

Considering that this syntax error can occur in multiple scenarios you might not be able to find your exact error in the list below.

Don’t worry about it, what matters is for you to learn the right approach to identify what’s causing the error and knowing how to fix it.

And going through the examples below you will learn how to do that.

In some of the examples I will show you how to fix this error if it happens while executing a single command in a Bash shell.

In other examples we will look at Bash scripts that when executed fail with the “unexpected token” error.

To fix the error in a single command it’s usually enough to add or remove some incorrect characters that cause the syntax error in the command.

Knowing how to fix the error in a script can take a bit more time, and for that I will use the following 5-step process:

  1. Run the script that contains the syntax error.
  2. Take note of the line mentioned by the Bash error.
  3. Execute the line with the error in a Bash shell to find the error fast (without having to change the script and rerun it multiple times).
  4. Update your script with the correct line of code.
  5. Confirm the script works.

Makes sense?

It’s time for the first scenario.

Let’s say I have the following file on my Linux system:

-rw-r--r--  1 ec2-user ec2-user   28 Jun 28 22:29 report(july).csv

And I want to rename it to report_july.csv.

I can use the following command, right?

mv report(july).csv report_july.csv

When I run it I get the following error:

-bash: syntax error near unexpected token `('

But, why?

Because parentheses () are used in Bash to create a subshell. In other words they are special characters.

And Bash special character need to be escaped if used as normal characters in a command. The backslah is used to escape characters.

I will update the command to include the backslash before both parentheses:

mv report(july).csv report_july.csv

No errors this time:

-rw-r--r--   1 ec2-user ec2-user   28 Jun 28 22:29 report_july.csv

Lesson 1: Remember to escape Bash special characters when you use them as normal characters (literals) in a filename or string in general.

First error fixed!

Syntax Error Near Unexpected Token Then (Example 1)

And here is the second scenario.

When I run the following script:

#!/bin/bash

DAY="Monday"

if[ $DAY == "Monday" ]; then
  echo "Today is Monday"
else
  echo "Today is not Monday"
fi

I get back the error below:

(localhost)$ ./unexpected_token.sh
./unexpected_token.sh: line 5: syntax error near unexpected token `then'
./unexpected_token.sh: line 5: `if[ $DAY == "Monday" ]; then'

Can you see why?

The error is caused by the missing space between if and the open square bracket ( [ ).

And the reason is the following:

if is a shell builtin command and you might be thinking you are using if here. But in reality the shell sees if[ that is not a known command to the shell.

At that point the shell doesn’t know how to handle then given that it hasn’t found if before, and it stops the script with the error above.

The correct script is:

#!/bin/bash

DAY="Monday"

if [ $DAY == "Monday" ]; then
  echo "Today is Monday"
else
  echo "Today is not Monday"
fi

I have just added a space between if and [ so the shell can see the if command.

And the output of the script is correct:

(localhost)$ ./unexpected_token.sh
Today is Monday

Lesson 2: Spaces are important in Bash to help the shell identify every command.

Syntax Error Near Unexpected Token Then (Example 2)

While writing Bash scripts, especially at the beginning, it’s common to do errors like the one below:

(localhost)$ for i in {0..10} ; do echo $i ; then echo "Printing next number" ; done

When you run this one-liner here’s what you get:

-bash: syntax error near unexpected token `then'

Let’s find out why…

The syntax of a for loop in Bash is:

for VARIABLE in {0..10}
do
  echo command1
  echo command2
  echo commandN
done

And using a single line:

for VARIABLE in {0..10}; do echo command1; echo command2; echo commandN; done

So, as you can see the semicolon is used in Bash to separate commands when you want to write them on a single line.

The reason why the semicolons were not required in the first version of the script is that the newline is a command separator too.

Now, let’s go back to our error…

The one-liner that was failing with an error contains the then statement that as you can see is not part of the structure of a for loop.

The error is telling us:

  • There is a syntax error.
  • The token ‘then‘ is unexpected.

Let’s confirm the one-liner runs well after removing then:

(localhost)$ for i in {0..10} ; do echo $i ; echo "Printing next number" ; done
0
Printing next number
1
Printing next number
2
Printing next number
3
Printing next number
4
Printing next number
5
Printing next number
6
Printing next number
7
Printing next number
8
Printing next number
9
Printing next number
10
Printing next number

All good!

Lesson 3: When you see a syntax error verify that you are using Bash loops or conditional constructs in the right way and you are not adding any statements that shouldn’t be there.

Syntax Error Near Unexpected Token Done

I have created a simple script in which an if statement is nested inside a while loop. It’s a very common thing to do in Bash.

#!/bin/bash

COUNTER=0
  
while true 
do
  if [ $COUNTER -eq 0 ]; then
    echo "Stopping the script..."
    exit 1
  done
fi

This script might seem ok, but when I run it I get the following…

./unexpected_token.sh: line 8: syntax error near unexpected token `done'
./unexpected_token.sh: line 8: `  done'

Why?

The done and fi statements are correctly used to close the while loop and the if conditional statement. But they are used in the wrong order!

The if statement is nested into the while loop so we should be closing the if statement first, using fi. And after that we can close the while loop using done.

Let’s try the script:

(localhost)$ ./unexpected_token.sh 
Stopping the script...

All good now.

Lesson 4: Nested loops and conditional statements need to be closed in the same order in which they are opened.

Syntax Error Near Unexpected Token fi

Let’s look at another scenario in which this syntax error can occur with the fi token:

#!/bin/bash
  
for NAME in 'John' 'Mark' 'Kate'
do
    if [ "$NAME" == 'Mark' ] then
        echo 'Hello Mark!'
    fi
done

And this is what I get when I run it:

./unexpected_token.sh: line 7: syntax error near unexpected token `fi'
./unexpected_token.sh: line 7: `    fi'

In this case the Bash shell identifies the if statement and because of that it expects then after it.

As you can see then is there, so what’s the problem?

There is no command separator between the [ ] command (yes….it’s a command) and the then statement.

So, what’s the fix?

Add a command separator immediately after the closing square bracket. We will use the semicolon ( ; ) as command separator.

Our script becomes:

#!/bin/bash
  
for NAME in 'John' 'Mark' 'Kate'
do
    if [ "$NAME" == 'Mark' ]; then
        echo 'Hello Mark!'
    fi
done

And if I run it I get the correct output:

(localhost)$ ./unexpected_token.sh 
Hello Mark!

Lesson 5: Remember to specify command separators in your Bash scripts. Either the semicolon or the newline.

Conclusion

You now have what you need to understand what causes this syntax error in your scripts. You can apply the 5 lessons I have explained in this guide to find a fix.

Take the time to review the lessons at the end of each section so they become part of your Bash knowledge.

If you have any questions please feel free to write them in the comments below.

Now, let’s say you have saved your Bash script using Windows.

And when you run it in Linux you are seeing a syntax error that you can’t really explain because the script looks correct to you.

You might be having the problem explained in this article.

Enjoy your scripting!


Related FREE Course: Decipher Bash Scripting

Related posts:

I’m a Tech Lead, Software Engineer and Programming Coach. I want to help you in your journey to become a Super Developer!

The if starting at:

if [ $? == 0 ]; then
  echo "User Already Exists : Error adding user with username ...
  exit 1
else

is ended with the done instead of the fi that is required.

The while loop starting a couple of lines earlier:

cat userlist.txt | while read uname password gname fullname

is missing its do (another bug); if that was present, then it would also need the done at the end. Someone lost track of the indentation. (Using 2 characters per level is better than 0 or 1, but it is easier to track levels if you use 4 spaces per level.) Note that the shell hasn’t gotten around to complaining about the lack of do because the syntax for a while loop is:

while cmd1
      cmd2
      cmd3 ...
do

and as far as the shell is concerned, it is still processing commands in the list cmd1, cmd2, cmd3, ....


Here’s a semi-decently indented version of the script. There was a missing fi at the top of the script, too.

#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
#         Assign encryped passwords to each user
#         Add users to groups or create new groups for these users
#         Report errors and successful operations where necessary in log files
#         post help options (echo)

#Root validation
if [[ $(id -u) -eq 0 ]]
then
    #Argument validation
    if [[ -z "$1" ]]
    then
        echo "No arguments found!"
        echo "Please include a user detail text file as first argument"
        echo "Please include a report text file as second argument"
        echo "Please include an error report text file as the third argument"
        echo "Use the -h argument (i.e. ./script -h) for help"
        exit 1
    fi
fi

#Help validation and Help file
if [[ "$1" = "-h" ]]
then
    echo "This is the help information file"
    echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
    echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
    echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
    exit
fi

#Reads first argument as user detail file for data
cat userlist.txt | while read uname password gname fullname
do
    #Reads /etc/passwd for Username
    egrep -w "^$uname" /etc/passwd
    #If Username is found then error reports
    if [ $? == 0 ]
    then
        echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Successes1.log
        exit 1
    else
        #Reads /etc/group for Groupname
        egrep -w "^$gname" /etc/group
        #If Groupname is found then nothing
        if [ $? == 0 ]
        then
            echo ""
        else
            #If Groupname not found then creates new group and reports
            groupadd "$gname"
            echo "Group Not Found: New Group $gname was created" >> Successes1.log
        fi
        #Retrieves Date
        createddate=$(date)
        #Perl password script takes input from Userlist
        pass=$(perl -e 'print crypt($ARGV[0], "Password")' $pass)
        #Adds Users with variables from userlist
        useradd "$uname" -g "$gname"  -c "$fullname" -p "$pass"
        #Reports information to successlist and errorlist report files
        if [ $? == 0 ]
        then
            groupid=$(id -g $uname)
            userid=$(id -u $uname)
            echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
        else
            groupid=$(id -g $uname)
            userid=$(id -u $uname)
            echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
            echo "Error: Must be root user to execute script"
            exit
        fi
    fi
done

There is still much room for improvement. The root validation block should exit if the user is not root; that happens instead a mile further down inside the loop. You can check the number of arguments better: $# gives you the number of arguments. If I tried yourscript.sh '' arg2 arg3, you’d claim there were no arguments when in fact the problem is that $1 is present but is an empty string. The standard convention for reporting how to use a command is something like:

echo "Usage: $0 usernames report errors" 1>&2

This reports the command’s name, and the arguments expected. The 1>&2 sends the message to standard error instead of standard output. The logic here is a little bizarre even so. You check that the user is root and only then check that there are arguments. If the user is not root, you don’t check the arguments. Not entirely sensible, I submit.

We can debate the UUOC (Useless Use of Cat). There’s actually an award for it; I don’t think this qualifies. However, it would be possible to write:

while read uname password gname fullname
do
    ...
done < $1

Hmmm…the script is supposed to take a file name argument that specifies the users, but the cat takes a fixed file name, not the file name argument!

Similarly, arguments 2 and 3 are studiously ignored; the log files are hard-coded.

egrep -w "^$uname" /etc/passwd
#If Username is found then error reports
if [ $? == 0 ]

This fragment can be improved several ways:

if egrep -w "^$uname:" /etc/passwd >/dev/null 2>&1
then
    #If Username is found then error report

This tests the exit status of the egrep command directly; it also prevents a new user roo from being treated as pre-existing because of user root. It sends the output and error output to /dev/null so that you won’t see anything when the user does exist.

It might be better not to exit when the user name is found; you could at least try to process the next entry. It is also odd that the report that the user exists (which terminates the processing) is recorded in Successes1.log rather than in Errors1.log; it is treated like an error.

The group check constructs are similar and should be similarly upgraded.

You read the password into $password with the read line; when it comes to creating the password, though, you have:

pass=$(perl -e 'print crypt($ARGV[0], "Password")' $pass)

On the first cycle, $pass is empty (most probably); you should have used $password in double quotes at the end:

pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")

As with the egrep commands, you can check the status of the useradd command directly too. It is a bit sweeping to say if [ $? == 0 ] is the mark of a tyro, but it isn’t too far off the truth.

The final exit in the script should be exit 1 to indicate an error exit. As already noted, this is preceded by the comment about ‘you must be root’, even though there was a check at the top for root privileges.

Caveat: I’ve not attempted to run the script; I could easily have missed some issues. It does, however, pass sh -v -n, so there are no gross syntactic errors left.

Once a shell script is syntactically correct, then you normally debug it using sh -x script (or, if it takes arguments, then sh -x script arg1 arg2 arg3 ...). This is the execution trace mode. The shell tells you, more or less inscrutably, what it is doing. The information is written to standard error. You can even trap the output for later scrutiny if you like with:

sh -x script arg1 arg2 arg3 2>script-x.log

The 2>script-x.log notation sends the standard error to the file script-x.log (choose your own meaningful name; I often use x or xxx for files I won’t want to keep, but I also remove such files without necessarily even looking at them because I know they are throwaway files).

I am getting syntax error near unexpected token done while executing my shell script:

while read filename
do
  echo "$filename"
  if [ -s $filename ]; then
    tail -10 $filename | grep `date '+%Y-%m-%d'` >> $lastlines1
    echo "- Next Error File - " >> $lastlines1
  done
  else
  echo " no errrors"
fi

Any ideas, where am I going wrong?

mtk's user avatar

mtk

25.8k34 gold badges89 silver badges127 bronze badges

asked Jan 2, 2013 at 12:19

UNIX Learner's user avatar

1

you are closing the while before the if.

while read filename 
do 
    echo "$filename" 
    if [ -s $filename ]
    then 
        tail -10 $filename | grep date '+%Y-%m-%d' >> $lastlines1 
        echo "- Next Error File - " >> $lastlines1 
    else 
        echo " no errrors" 
    fi
done

answered Jan 2, 2013 at 12:23

BitsOfNix's user avatar

BitsOfNixBitsOfNix

4,9672 gold badges25 silver badges34 bronze badges

Let’s add some new lines and indentation:

1 while read filename; do
2     echo "$filename"
3     if [ -s $filename ]; then
4         tail -10 $filename | grep date '+%Y-%m-%d' >> $lastlines1
5         echo "- Next Error File - " >> $lastlines1
6     done
7 else
8     echo " no errrors"
9 fi

lines 6 and 9 seem to be swapped. In other words the while-do-done and if-then-else-fi clauses are overlapping. Which is wrong in shell (and most other computer languages).

answered Jan 2, 2013 at 12:29

peterph's user avatar

peterphpeterph

30k2 gold badges67 silver badges74 bronze badges

You need to use vim editor for scripting , it will shows text in RED if that syntax wrong

while read FileName 
do 
        echo "${FileName}" 

        if [ -s "${FileName}" ]; then 
            tail -10 $FileName | grep "date '+%Y-%m-%d'" >> "${lastlines1}"
            echo "- Next Error File - " >> "${lastlines1}"
        else 
            echo " no errrors" 
        fi      
done

answered Jan 2, 2013 at 12:29

Rahul Patil's user avatar

Rahul PatilRahul Patil

23.6k25 gold badges79 silver badges95 bronze badges

3

You need to complete the if statement before the do while. If you are trying to only echo no errors once if no files are found, you need to use a flag to indicate it.

errorCount=0
while read filename 
do 
    echo "$filename" 
    if [ -s $filename ]
    then 
        tail -10 $filename | grep date '+%Y-%m-%d' >> $lastlines1 
        echo "- Next Error File - " >> $lastlines1 
        errorCount=$(($errorCount + 1))
    fi
done
if [[ $errorCount -eq 0 ]]
then
    echo " no errors"
fi

answered Jan 2, 2013 at 14:37

Drake Clarris's user avatar

Sometimes this error happens because of unexpected CR characters in file, usually because the file was generated on a Windows system which uses CR line endings. You can fix this by running dos2unix or tr, for example:

tr -d '15' < yourscript.sh > newscript.sh

This removes any CR characters from the file and in new shell script file you didn’t get that error.

answered Feb 27, 2017 at 6:09

Mihit Gandhi's user avatar

Кодирование в терминале Linux Bash стало преобладающей практикой в ​​секторе кодирования. Инженеры-программисты и студенты, изучающие язык программирования, сталкиваются с различными ошибками. Если вы неоднократно сталкивались с такими ошибками, как Синтаксическая ошибка рядом с неожиданным токеном ‘(‘ или Синтаксическая ошибка Bash рядом с неожиданным токеном, вы можете попробовать использовать методы, описанные в статье, и стать опытным программистом. Прочитайте методы, описанные в статье, в разделе порядок описан и исправьте ошибки в командных строках вашего файла.

Linux Bash — интерпретатор командной строки для системы на базе Linux, заменяющий Bourne Shell или sh. Файлы именуются в формате .sh в сценариях Linux Bash. Если в коде сценария оболочки есть проблемы с форматированием, вы можете столкнуться с синтаксической ошибкой. Если ошибка близка к символу (, оболочка подскажет вам ошибку в строке и отобразит ошибку в соответствующей строке. Поскольку Linux Bash является интерпретатором, строка с ошибкой будет возвращена вам в Терминал, и он прекратит сканирование остальных команд в сценарии. Следовательно, вам необходимо исправить ошибку в конкретной командной строке и перейти к следующей, чтобы исправить непредвиденную ошибку токена в сценарии оболочки. Причины синтаксиса ошибка рядом с неожиданным токеном в Linux Bash перечислены ниже в этом разделе, как показано ниже:

  • Кодирование с помощью escape-последовательностей. Если вы написали код в сценарии Bash, escape-последовательности или кавычки в сценарии могут вызвать ошибки. Чтобы исправить ошибку, управляющие последовательности и кавычки должны быть записаны в правильном формате.

  • Неправильный синтаксис в файле кодирования. Синтаксис в коде может привести к синтаксической ошибке, если команда написана с неправильным синтаксисом, например, с изменением порядка циклов.

  • Неправильное использование команды. Если вы неправильно используете команду, например, присваиваете неверное значение, у вас может возникнуть синтаксическая ошибка.

  • Несовместимая ОС в системах. Если оболочка для сценария кодирования несовместима между системами Unix и DOS, у вас может возникнуть непредвиденная ошибка.

  • Проблемы в сценарии оболочки bash. Проблемы, выполняемые в сценарии оболочки bash в файле, скопированном из другой системы, могут привести к непредвиденной ошибке токена.

Рассмотрим файл с именем example.sh, созданный в сценариях Linux Bash со следующими командными строками для пояснений. Файл примера допускает синтаксические ошибки и включает все возможные команды, которые можно использовать в сценарии оболочки.

str= ‘First command line of ‘(example file)’ in the script’
str= [(1,2),(3,4)]
if[ $day == “mon” ] then
 echo “mon”
else
 echo “no mon”
fi
for VARIABLE in {0..2}; then
do echo command1; echo command2; echo command3; echo command4; done
while true; do if [ $ day == “mon” ]; then echo “mon”; else echo “not mon”; done; fi

Способ 1: исправить ошибки в каждой командной строке вручную

Первый способ исправить ошибки — исправить синтаксическую ошибку вручную в каждой командной строке скрипта. В этом разделе обсуждаются шаги по устранению синтаксических ошибок рядом с неожиданным токеном в командных строках. Процесс исправления непредвиденной ошибки токена в Терминале описан ниже. Запустите файл в Терминале, введя команду ./example.sh и нажав клавишу Enter.

2. Обратите внимание на строки с непредвиденной ошибкой токена в командных строках результата ниже.

3. Исправьте ошибку в каждой строке, следуя описанным ниже методам по отдельности и сохранив файл.

4. После внесения изменений снова запустите файл и проверьте, устранена ли синтаксическая ошибка в файле.

Шаг I: Чтение содержимого файла

Первым шагом к устранению синтаксической ошибки в командной строке является чтение файла в Терминале. ЕСЛИ есть проблемы с файлом, возможно, вы не сможете просмотреть файл. Обычная практика просмотра файла заключается в запуске файла с помощью команды ./example.sh, но вы не можете изменить содержимое файла. Варианты просмотра содержимого файла и изменения командных строк для исправления синтаксической ошибки рядом с неожиданным токеном ‘(‘ обсуждаются ниже.

Вариант 1: через CAT-команду

Первый вариант — использовать команду cat для просмотра файла в сценарии оболочки. Прочтите содержимое файла с неожиданной ошибкой токена с помощью команды cat, введя команду cat –v example.sh в Терминале.

Примечание 1. Файл example.sh используется в пояснительных целях, и вам необходимо ввести имя файла с непредвиденной ошибкой токена.

Примечание 2. Команда cat –v используется для отображения всех невидимых символов, которые могут представлять собой возврат каретки или пробел без разрыва.

Вариант 2: Через команду VX

Если вы не можете использовать команду cat, вы можете попробовать использовать команду vx для просмотра и изменения команд в файле, используя шаг, указанный ниже. Введите команду sh –vx ./example.sh в Терминале, чтобы открыть файл.

Вариант 3: Через od –a Command

3. Если в командной строке есть несколько невидимых символов, вы можете использовать команду od –a для просмотра файла. Если содержимое файла не видно в файле кода, вы можете попробовать прочитать файл, используя команду od –a example.sh для изменения кода.

Шаг II. Удалите разрывы строк Windows

Если в сценарии оболочки есть разрывы строк Windows, вы можете использовать консольные команды, чтобы удалить разрывы строк и скопировать строки кода в новый файл, чтобы исправить ошибку.

Введите следующую команду в Терминале, чтобы сохранить содержимое файла в другой файл с именем correctedexample.sh, чтобы удалить разрывы строк Windows в сценарии.

tr –d ‘r’ <example.sh> correctedexample.sh

Шаг III: Установите разрешения для вновь созданного файла

Вам необходимо установить разрешение для вновь созданного файла для редактирования файла, чтобы файл можно было выполнить в оболочке. Введите команду как chmod 755 correctedexample.sh в Терминале, чтобы предоставить права доступа к файлу и запустить файл. Теперь вы можете просмотреть исправленный файл и исправить проблемы с форматированием, а также исправить синтаксическую ошибку рядом с неожиданным токеном ‘(‘ в файле.

Шаг IV: форматирование кода в файле

Второй шаг — отформатировать строки кода по отдельности и вручную изменить командные строки в файле. Варианты форматирования файла для исправления синтаксической ошибки рядом с неожиданным токеном ‘(‘ обсуждаются ниже в этом разделе.

Вариант 1: заменить одинарные кавычки двойными кавычками

Если вы используете одинарные кавычки в командной строке, вам нужно изменить команду, заменив одинарную кавычку двойными, чтобы исправить синтаксическую ошибку. В файле example.sh удалите строки кода, содержащие ‘ и ‘ или одинарные кавычки в команде, и замените одинарные кавычки двойными кавычками или » и ». Здесь, в файле примера, вам нужно изменить код как str= «Первая командная строка «(файл примера)» в скрипте»

Примечание. Двойные кавычки необходимы для команд типа параметра, таких как str= “[(1,2),(3,4)]».

Вариант 2: добавить $ к строковым строкам

Если вы добавили строковые значения в скрипт, вам нужно добавить $ к строковым значениям, чтобы исправить синтаксическую ошибку в скрипте. Добавьте $ для командных строк со строковыми значениями, чтобы исправить непредвиденную ошибку. Здесь, в файле примера, измените командную строку как;

str= $ ‘First command line of ‘(example file)’ in the script’

Примечание. Если вы используете $ в строковом значении, вы можете обойти escape-последовательность обратной косой черты, поскольку командные строки декодируются по стандарту ANSI C. Другими словами, используя $ для строкового значения, вы можете избежать использования двойных кавычек вместо одинарных в командных строках.

Вариант 3: преобразовать вкладки в пробелы

Пробелы, которые вы оставили между двумя операторами в команде, должны быть пробелами, а не табуляцией, чтобы исправить синтаксическую ошибку в сценарии. Если вы получаете ошибку на Cygwin, вы можете попробовать преобразовать вкладки в кодах в пробелы, чтобы исправить ошибку. Командная строка представлена ​​ниже как;

do echo command1;       echo command2;             echo command3;             echo command4;             done

Приведенную выше команду следует переписать, как показано ниже, чтобы исправить ошибку.

do echo command1; echo command2; echo command3; echo command4; done

Вариант 4. Используйте escape-символы

Если вы используете символ bash, важно использовать escape-символ вместе с символом bash, чтобы исправить синтаксическую ошибку. Круглые скобки или () являются специальными символами bash в файле, поэтому вам нужно будет использовать escape-символ или обратную косую черту в командной строке, чтобы экранировать обычные символы для выполнения команды. Команда str= ‘Первая командная строка ‘(пример файла)’ в команде script’ не выдаст ошибку в Терминале, поскольку используется escape-символ.

Вариант 5. Используйте пробелы между символами

Сценарий оболочки распознает команды и операторы в сценарии по значениям по умолчанию. Вам необходимо обеспечить правильное использование пробелов между символами, чтобы оболочка могла идентифицировать команду, указанную в сценарии. Пробел — это символ, который используется для различения двух символов в командной строке. В коде нет пробела между if и [, which gives the unexpected token error as the if[ command is not identified by the shell. If the code is changed to if [ $ day == “mon” ]; тогда ошибка может быть решена с помощью команды бюллетеня оболочки, если она идентифицируется оболочкой.

Вариант 6. Используйте разделитель команд для операторов

Различные команды в сценарии оболочки должны быть разделены на операторы, чтобы Терминал мог идентифицировать отдельные команды. Вам нужно использовать разделитель команд, чтобы исправить синтаксическую ошибку в Linux Bash. Операторы в команде должны быть разделены разделителем команд, таким как точка с запятой или ; или новую строку, нажав клавишу Enter. Например, команда в коде if [ $ day == “mon” ] тогда нужно изменить, как если бы [ $ day == “mon” ]; затем исправить ошибку. Поскольку точка с запятой используется в качестве разделителя команд между символами [ and then, you can fix this error.

Option 7: Remove Additional Statements

Sometimes, you may have added additional statements or may have mixed up the codes in case of multiple nested loops. You need to remove the additional statements on the command lines to fix the Syntax error near unexpected token ‘(’ in the Linux Bash. The bash loops for…done or and the constructional constructs if… fi needs to be in the correct syntax. The example file has the wrong syntax in the for loop has the term then which is used in the if statement. Modifying the code as the following code will fix the unexpected token error. The statement then is an additional statement in the code and removing the term will fix the error.

for VARIABLE in {0..2}; do echo command1; echo command2; echo command3; echo command4; done 

Option 8: Ensure Order of Closing of Statements is Correct

If you are using many nested or conditional construct statements in the shell script, you have to ensure that the loops are closed in the order they are opened. You can use a new line separator to avoid conflicts with the loops. The order of closing the nested loops and conditional statements should be correct and must not be altered. The loops in the code while true; do if [ $ day == “mon” ]; затем эхо «мон»; иначе эхо «не пн»; Выполнено; fi нужно закрывать в правильном порядке. Изменение кода, как показано ниже, может исправить непредвиденную ошибку токена, поскольку порядок закрытия операторов исправлен.

while true; do if [ $ day == “mon” ]; then echo “mon”; else echo “not mon”; fi; done

Способ 2: переписать код

Если вы скопировали код и вставили его в новый файл в Терминале, вы можете попробовать переписать код вручную, чтобы исправить ошибку. Ошибки в коде можно исправить, если вы написали код без каких-либо ошибок формата в сценарии оболочки. Это связано с тем, что скрытые символы и проблемы с форматированием в текстовом редакторе, таком как Microsoft Word, которые вы могли использовать для копирования и вставки кода, могли привести к ошибке.

Способ 3: используйте команду Dos2unix.exe

Если вы используете операционную систему Unix, вы можете писать коды с символом перевода строки как n, чтобы перейти к следующей строке в файле. Однако, если вы используете ОС Windows, вам нужно перейти к следующей строке в коде, используя возврат каретки и перевод строки или rn в файле. Если вы выполняете код, написанный в ОС Windows, в Cygwin, вы можете получить синтаксическую ошибку рядом с неожиданным токеном ‘(‘.

Чтобы исправить ошибку, вам нужно очистить символы возврата каретки, используя инструмент командной строки DOS в Unix в качестве конвертера формата текстового файла. Введите следующую команду как dos2unix.exe example.sh в терминале, и вы сможете преобразовать файл в формат Unix.

***

В статье обсуждались основные методы исправления синтаксической ошибки Bash рядом с неожиданным токеном ‘(‘ в сценарии. Если вы используете Linux Bash, вы можете использовать методы, описанные в этом разделе, для исправления синтаксической ошибки Bash рядом с неожиданным токеном. Если вы Если вы прочитали всю статью и нашли ее содержание полезным, сообщите нам о своих предложениях и вопросах в разделе комментариев.

The error message syntax error near unexpected token `(‘ occurs in a Unix-type environment, Cygwin, and in the command-line interface in Windows. This error will most probably be triggered when you try to run a shell script which was edited or created in older DOS/Windows or Mac systems.

Syntax Error near unexpected token `('

Syntax Error near unexpected token `(‘

This error message also surfaces when you are entering commands in the Linux command line for everyday tasks such as copying files manually etc. The main reasons why this error message occurs is either because of bad syntax or problem of the OS in interpreting another system’s commands/shell.

The reasons for this error message are very diverse and cannot be listed in one article as there are thousands of possibilities of syntax going wrong when executing commands. The core reasons for this error are:

  • Bad syntax when executing any command in either platform. Either you are not using the command correctly or have entered the wrong syntax.
  • The shell is not compatible between Unix/DOS systems.
  • There are issues running the bash shell script from another source.

In this article, we assume that you know the basics of coding and have an idea what you are doing. If you are a beginner, it is best that you follow in-depth tutorials of the language/command which you are trying to execute. You probably have made a mistake of some syntax.

Solution 1: Checking Syntax and Format of commands

The first and foremost reason why you might experience this error message is that of bad syntax in your code or you not following the exact format of the commands. Each command has a predefined format which you can see in its documentation. Several parameters are optional which others are mandatory.

Furthermore, extra care should be taken for extra space, use of double quotes, and the mandatory parameters required. If any of them are missing or have been declared incorrectly, you will not be able to execute your code.

For example, instead of the following code

[mycom7] # ./ctopo.sh um_test1 [(1,2),(2,1)]

You need to execute it as

[mycom7] # ./ctopo.sh um_test1 "[(1,2),(2,1)]"

Also, make sure that you are executing your commands/shell script correctly if it is spanning several lines.

Because of the parameter type, the double quotes are necessary. An extra space might also ruin your code and force the error message. Make sure that you check the official documentation of the command you are executing and see if there is a problem there.

Solution 2: Troubleshooting your shell script

If are using a shell script which works in the source system but returns an error in the target, you can troubleshoot the script by checking the variables which are stored during the execution and then see what is causing the issue. This is a very common cause as in several cases, the shell tries to interpret an unprintable character.

Try running the shell with the parameter of ‘vx’. This will show us what commands are being run and what values are stored in the script. Through here you can troubleshoot and diagnose what is going wrong.

For example, execute the script in the terminal after including ‘vx’ as:

# sh -vx ./test_script5.sh

You can check the contents of the script using the ‘cat’ command as:

# cat test_script5.sh

Solution 3: Using ‘dos2unix.exe’ command

In Windows/DOS text files, a new line is a combination of a Carriage Return (r) followed by a Line Feed (n). In Mac (before Mac OS X), a line break used a simple Carriage Return (r). Unix/Linux and Mac OS X use Line Feed (n) line breaks. If you are using Cygwin, it will fail to process the scripts made by DOS/Windows and older Mac because of the extra Carriage Return (r) character.

Using 'dos2unix.exe' command

Using ‘dos2unix.exe’ command

Here you can make of ‘dos2unix.exe’ command which will convert the script to the correct format and then you can execute it without any issues.

To conclude, you need research your commands and type of platform you are using and make sure there are not any discrepancies. Since we cannot cover each and every possibility, you would have an idea what kinds of errors can occur and how to fix them.

Photo of Kevin Arrows

Kevin Arrows

Kevin is a dynamic and self-motivated information technology professional, with a Thorough knowledge of all facets pertaining to network infrastructure design, implementation and administration. Superior record of delivering simultaneous large-scale mission critical projects on time and under budget.

  1. Fix Syntax and Formatted Strings to Solve bash: syntax error near unexpected token Error in Bash
  2. Use the dos2unix Command to Solve bash: syntax error near unexpected token Error in Bash

Solve Syntax Error Near Unexpected Token in Bash

Writing code with Bash scripting, escape sequences or quotation marks may cause errors. This article will explain how to solve the bash: syntax error near unexpected token error in Linux Bash.

There are many code-related reasons for getting a syntax error near unexpected token in Bash scripting. We will explain the most common mistakes and ways to fix them.

Fix Syntax and Formatted Strings to Solve bash: syntax error near unexpected token Error in Bash

If you are getting this error, you most likely made a syntax error. First, read the file’s contents with the cat command.

Note the use of single-quote and double-quote characters.

If you are using escape characters, you must use double quotes. Single quotes do not allow these characters.

For example, the following code will throw the syntax error near unexpected token '(' error.

#!/bin/bash
str='You '(cannot)' do this'

syntax error

However, if you write the same code with double quotes, you can use escape characters. The code below will work without errors.

#!/bin/bash
str="You "(can)" do this"

Also, another way to do this is to add the $ at the beginning of the string. In this way, strings in the form of $'string' are treated specially.

Backslash escape sequences are decoded as specified by the ANSI C standard.

#!/bin/bash
str=$'You '(can)' do this'

Use the dos2unix Command to Solve bash: syntax error near unexpected token Error in Bash

Unix operating systems use line feed ("n") as the end of the line, but Windows operating systems use carriage return and line feed ("rn"). So if you want to execute a code written in Windows with Cygwin, you may get this error.

You must clear the carriage return characters to execute the file.

The dos2unix command-line tool is a DOS to Unix text file format converter and vice versa. You can use this tool to make your file Unix compatible.

Its usage is as follows.

The file will be converted to Unix format. You can now execute the file.

I am trying to download flareget download manager via wget
I get error

wget  http://www.flareget.com/files/flareget/debs/amd64/flareget_2.3-24_amd64(stable)_deb.tar.gz
bash: syntax error near unexpected token `('

Why is that error coming and what is the solution for that?

asked Nov 8, 2013 at 10:27

Registered User's user avatar

Registered UserRegistered User

4,7349 gold badges35 silver badges43 bronze badges

1

You should use single quotes ' or double quotes " around the URL in this case (and in general):

wget  'http://www.flareget.com/files/flareget/debs/amd64/flareget_2.3-24_amd64(stable)_deb.tar.gz'

From now, you should use this method in general when you use a string which contain parentheses as argument in a command. That is because parentheses are used for grouping by the shell such that they are not communicated in any way to a command. So, the bash shell will give you a syntax error:

$ echo some (parentheses)
bash: syntax error near unexpected token `('
$ echo 'some (parentheses)'
some (parentheses)

answered Nov 8, 2013 at 10:30

Radu Rădeanu's user avatar

Radu RădeanuRadu Rădeanu

164k47 gold badges321 silver badges397 bronze badges

1

It’s because of the brackets. You need to escape them like this:

wget  http://www.flareget.com/files/flareget/debs/amd64/flareget_2.3-24_amd64(stable)_deb.tar.gz

Now it should work.

answered Nov 8, 2013 at 10:29

chaos's user avatar

2

Mine had nothing to do with un-escaped brackets and everything to do with an alias already being defined with the same name as the function.

Alias in one file:

alias foo="echo do something"

Function in another:

foo() {
    # Do something else
}

Both of these files were sourced by my ~/.bashrc, giving me the unhelpful error message:

syntax error near unexpected token (

Zanna's user avatar

Zanna

68.2k55 gold badges210 silver badges320 bronze badges

answered Nov 29, 2021 at 2:09

Andy J's user avatar

Andy JAndy J

1,0181 gold badge12 silver badges17 bronze badges

1

The error message syntax error near unexpected token occurs at an Unix-type ecosystem also at the command-line port in Windows. This error will be actuated should you attempt to conduct on a shell script that was edited or generated from elderly DOS/Windows or even Mac systems.

This error message also surfaces Whenever You Are entering Commands from the Linux command line to get regular tasks like replicating files manually. The explanations this error communication does occur will be because of bad syntax or difficulty of this OS in translating the other system’s commands/shell.

What does syntax error near unexpected token mean?

Syntax Error near unexpected token

This difficulty (syntax error near unexpected token) usually Does occur in Cygwin, a Unix-type of natural surroundings plus command-line port for Microsoft Windows.

It’s going to be actuated once You Attempt and conduct a shell script Which edited or was created from the Mac systems or Windows/DOS.

In Windows/DOS text files, a line is usually the most Blend of 2 characters such as a Carriage Return (janin ) that will be followed closely using a Line Feed (n) character.

Just Before Mac OS X Mac systems, a line fracture was The solitary Carriage Return (runciman ) character. Contemporary day Mac OS & Linux or Unix systems use this Unix mode Line Feed (n) line fractures.

Cygwin may neglect to procedure using the scripts which are Formatted in aged Mac OS or even Windows/DOS systems on account of the current clear presence of the further Carriage Return (runciman ) character.

What can cause Syntax Error near unexpected token

The Explanations for this particular error message Are Extremely varied and May perhaps not be recorded in 1 informative article since you will find hundreds and hundreds of chances of syntax moving erroneous when implementing commands. The center causes of this error are:

1. Bad syntax when implementing some command from the platform. Either way, you aren’t employing the command properly or possess entered the incorrect syntax.

2. The shell isn’t compatible in amongst Unix/DOS systems.

3. You’ll find problems conducting the celebration shell script out of the other supply.

In this Piece, we presume that you simply understand the Fundamentals of how Coding and possess a notion what it is you’re carrying out. If you’re just beginning, it’s better for you to simply just follow tutorials of this language/command that you’re working to perform. Now you have produced a blunder of a few syntaxes.

#Option 1: Make Use of the”dos2unix.exe” Command

Syntax Error near unexpected token solution

1. To resolve the issue of the error”syntax error near an unexpected token,” the consumers are wise to use this”dos2unix.exe” command.

2. This command will likely soon probably help transform the script into your Unix appropriate format.

#Option 2: Utilize the”cat” Command

If you are currently making usage of the Linux system, then You May trace The measures:

1. Use this”cat” command for showing contents of this script.

2. You can use these commands. Paste the text that is duplicated onto a fresh document. The record that is would visually look like the older 1. It will comprise the characters also certainly will get rid of the errors.

3. Place in the document that’s been designed so it could be implemented.

4. Operate the script using this”sh –vx. You’d See That the non-printing Characters”page1=186″ usually are perhaps not found there no more.

# Option 3: Deal with”echo$SHELL”

After you operate Being a Shell Script goal in almost any Xcode Undertaking And you experience this error, then you definitely fix this dilemma by:

1. Firstly all, tend not to label”celebration” &”sh”; you’ll need just one shell. You are able to type”echo$SHELL” for realizing that which shell you ought to use or place a shebang throughout the beginning of one’s script.

2. Put semicolons following the commands involving […] which functions for an alias to get”evaluation.” The Command Terminators Are Normally newline. As the terminators such as”,” “;” “&,” “II” and are compulsory. You may set commands amongst whether. That the semicolons have to be required.

# Option 4: Deal with”LF” & maybe not”CRLF”

Syntax Error near unexpected token

For consumers, the most error of syntax error near unexpected Token happened as a result of erroneous line end that would possibly be the consequence of”LF” & perhaps maybe not”CRLF.”

This occurred due to these consumers operating out of Your Windows Functioning System.

1. The consumers can check precisely the Same on Notepad++ :

2. View > Show Symbol > Show all characters

3. That may be repaired by Abiding by the measures too:

4. Edit > EOL Navigation > UNIX/OSX Format.

# Option 5: Deal with Misconfigured System Files

Syntax Error

The Syntax Error Near Unexpected Token is an error that’s Usually withstood from the existence of all system files.

These frequent Windows errors are usually less difficult to repair. In case You’ve acquired a”syntax error near unexpected token” communication, then their unlimited opportunities your pc system includes any registry problems. Accordingly, by downloading & conducting registry repair instrument as”Advanced System Repair,” then you may very easily correct this issue effortlessly.

At an Identical period, you can avoid Issues that are Extra From happening.

Once you have mended the registry, you are able to Conduct a fast Scan together with the assistance of this computer Health Advisor anti-malware software which is going to assist you in making sure your personal computer system has no problems.

Below Are Some Measures

  • Download & install the Advanced System Repair instrument. Today Scan your pc system using this particular specific application.
  • Select the choice “Repair All” icon when Your system has Completed the scanning procedure,
  • Download & Install the”Personal Computer Health Advisor Malware Removal” instrument.
  • The Personal Computer Health Advisor Malware Removal instrument can Assist in Assessing your personal computer by getting rid of all traces of malware such as spyware, adware, and more.
  • Choose the choice”Begin New Scan.”

#Option 6: Deal with: Normal Q A

Adjust the error”syntax error near unexpected token” by Abiding by these measures!

Unix Compared to Linux

You have possibly been aware of this expression. You likely understand It truly is a working system.

In fact, it Android functioning system. It works on various apparatus, including laptop computers and desktops. It really may be Chrome OS’s heart. You may put it; also, it runs on Windows Pi.

Now You Could Have also learned of Unix and that they Show up equivalent. And also you also may be wanting to know are they the same thing? Can they’re compatible?

UNIX was devised, Dennis Ritchie. You might have discovered those. Of course, to state, Dennis Ritchie is famous for making the C programming language.

Ken Thompson is for not easing lit famous UNIX, however, in addition, he established the character programming which we make utilization of all of the full time, and he’s your co-inventor of both all the Go programming language of Google.

Therefore we are coping with legends in calculating.

At the late 1960s early 1970s, both Thompson and Ritchie, together With people such as Kernighan, ended up applying a working system called Multics (Multiplexed Information and Computing Service). This has been constructed to conduct apps. See this video to get the whole heritage!

In Conclusion, you Will Need re Search your own commands along with Kind of Stage you’re utilizing and be certain there aren’t any discrepancies. Ever since we may do not protect every potential and each that you’d get Errors can happen and the best way you can repair them.

15.4. Probable Causes for Syntax Errors

15.4.1 Undefined and Misspelled Variables

As you know, the shells do not require variables to be declared. When a variable name is used in a program, the variable is created automatically. Although this may seem more convenient than having to declare every variable explicitly, there is an unfortunate consequence: An inadvertent spelling error might introduce an extra variable that you had no intention of creating. And because UNIX/Linux is case sensitive, even changing from uppercase to lowercase can cause a program to fail.

When setting a variable in the C/TC shells, the set command is used, and the = sign must be surrounded with space (or no space at all). The set command in bash, sh, and ksh is used to set shell options or create positional parameters, but is not used to define variables. Space is not allowed on either side of the = sign. When switching from one shell to another, it is easy to forget when to use set and when to use or not use spaces.

The C and TC shells will tell you when you are using an undefined variable. The Bourne, Bash, and Korn shells display a blank line, unless you request error checking with the set �u or the shell’s �u invocation option. The �u option flags any variables that have not been defined, called unbound variables.

In the Bourne, Korn, and Bash shells, a variable is set as follows:

x=5

name=John

friend="John Doe"

empty=   or empty=""

To check for undefined variables:

set -u

echo "Hi $firstname"



(Output)

ksh: firstname: parameter not set

In the C and TC shells:

set x = 5

set name = John

set friend = "John Doe"

set empty = ""

The shell checks for undefined variables:

echo "Hi $firstname"



(Output)

firstname: Undefined variable

Example 15.7.
    #!/bin/tcsh

1   set friend1 = "George"

    set friend2 = "Jake"

    set friend4 = "Danny"

2   echo "Welcome $friend3 "



(Output)

3   friend3: Undefined variable.

EXPLANATION

  1. Three variables are set. When variables are so similar in thier names, it is easy to mistype one of them later in the program.

  2. The variable friend3 was never defined.

  3. The C and TC shells send an error to let you know that you have an undefined variable. The Bourne, Korn, and Bash shells leave a blank line.

15.4.2 Incomplete Programming Statements

Missing Keywords

When using a programming statement such as an if statement or while loop, you may accidentally omit part of the statement. For example, you may forget to complete your while loop with the done keyword. Whenever you see an error message concerning unexpected end of file, or if the message points to the line number one past the last (e.g., your script contains 10 lines and the error message refers to line 11), you should check for incomplete programming statements.

Indentation

An easy way to ensure that if/else, while/do/done, case statements, and other contructs are complete is to indent the block of statements under each test expression (at least one tab stop), and move the terminating keyword (done, end, endsw, etc.) to line up with the conditional or looping command that it terminates. This is an extremely helpful technique when these constructs are nested.

if/endif Errors

See the following format for the correct way to set up your if/endif construct with tab stops.

FORMAT

In Bourne, Korn, and Bash shells:

# Without indentation

if [ $ch = "a" ]    # Use indentation

then

echo $ch

if [ $ch = "b" ]    <-- Missing 'then'

echo $ch

else

echo $ch

fi

        <-- Missing 'fi' for first 'if'

--------------------------Fix--------------------------

# With indentation

if [ $ch = "a" ]

then

    echo $ch

    if [ $ch = "b" ]

    then

       echo $ch

    else    # 'else' goes with nearest 'if'

       echo $ch

    fi

fi

In C and TC shells:

if ( $ch == "a" )     <-- Missing 'then'

     echo $ch

     if ( $ch == "b" ) then

          echo $ch

else

     echo $ch

endif

       <-- Missing 'endif' for first 'if'

--------------------------Fix--------------------------

if ( $ch == "a" ) then

     echo $ch

     if ( $ch == "b" ) then

          echo $ch

     else

          echo $ch

     endif

endif

case and switch Errors

There are a number of bugs often found in case and switch commands. The variable that is being tested should be in double quotes if the variable value consists of more than one word. Relational, logical, and equality operators are not allowed in the case constants.

FORMAT

Case statements for the Bourne, Korn, and Bash shells:

case $color in          <-- Variable should be quoted

blue)

   statements

   statements           <-- Missing ;;

red || orange)          <-- Logical || not allowed

   statements

      ;;

*)  statements

      ;;

                         <-- Missing esac

-----------------------The Fix--------------------------------

case "$color" in

blue )

   statement

   statement

      ;;

red | orange )

   statements

      ;;

*)

   statements

      ;;

esac

Switch statements for C and TC shells:

switch ($color)          <-- Variable should be quoted

case blue:

   statements

   statements            <-- Missing breaksw

case red || orange:      <-- Logical operator not allowed

   statements

   breaksw

default:

   statements

   breaksw

                          <-- Missing endsw

-----------------------The Fix--------------------------------

switch ("$color")

case blue:

   statements

   statements

   breaksw

case red:

case orange:

   statements

   breaksw

default:

   statements

   breaksw

endsw

Looping Errors

A looping error occurs when the syntax of a for, foreach, while, or until loop is incorrect, most commonly when one of the keywords used to terminate the looping block is omitted, such as do, done, or end.

FORMAT

Bourne shell:

while  [ $n -lt 10 ]      <-- Missing do keyword

   echo $n

   n=`expr $n + 1`

done



while  [ $n -lt 10 ]

do

   echo $n

   n=`expr $n + 1`

                            <-- Missing done keyword

-----------------------The Fix--------------------------------

 while  [ $n -lt 10 ]

do

   echo $n

   n=`expr $n + 1`

done

Loops for Bash and Korn shells:

while  (( $n <= 10 ))    <-- Missing do keyword

   echo $n

   (( n+=1 ))

done



while  (( $n <= 10 ))

do

   echo $n

   (( n+=1 ))

                          <-- Missing done keyword

-----------------------The Fix--------------------------------

while  (( $n <= 10 ))

do

   echo $n

   (( n+=1 ))

done

Loops for the C and TC shells:

while ( $n <= 10 )

   echo $n

   @n+=1                 <-- Missing space after the @ symbol

                         <-- Missing end keyword

foreach ( a b c )        <-- Missing variable after foreach

   echo $char

end

-----------------------The Fix--------------------------------

while ( $n <= 10 )

   echo $n

   @ n+=1

end



foreach char ( a b c )

   echo $char

end

Operator Errors

The shells use different operators for manipulating strings and numbers. The Bourne shell uses the test command (see man test) and its operators for comparing numbers and strings. Although these operators will work with Korn and Bash shells, normally they are not used. Instead, the Korn and Bash shells provide a set of C-like operators to handle arithmetic with the let command (( )) and string operators to be used with the new test command [[ ]]. But the Korn shell does not use the double == sign for equality, whereas the Bash shell does.

The C and TC shells also provide a set of C-like operators for comparing numbers and strings, and use the == for both numbers and strings. Confusing? If you are porting shell scripts, it might be a good idea to check the operators for each shell. They are provided in tables for each shell in this book. (See Appendix B.) The following examples illustrate some of the operators for each shell.

FORMAT

Bourne shell:

Numeric testing

   if [ $n -lt 10 ]

   if [ $n -gt $y ]

   if [ $n -eq 6 ]

   if [ $n -ne 6

String testing

   if [ "$name" = "John" ]

   if [ "$name" != "John" ]

Korn shell:

Numeric testing

   if (( n < 10 ))

   if (( n >  y ))

   if (( n == 6 ))

   if (( n != 6 ))

String testing

   if [[ $name = "John" ]]

   if [[ $name != "John" ]]

Bash shell:

Numeric testing

   if (( n < 10 ))

   if (( n >  y ))

   if (( n == 6 ))

   if (( n != 6 ))

String testing

   if [[ $n == "John" ]]

   if [[ $n != "John" ]]

C and TC shells:

Numeric testing

   if ( $n < 10 )

   if ( $n >  $y )

   if ( n == 6 ))

   if ( n != 6 )



String testing

   if ( "$name" == "John" )

   if ( "$name" != "John" )

Misusing an Operator

The following examples illustrate the most common causes of misused operators.

Example 15.8.
(sh)

1   n=5; name="Tom"

2   if [ $n > 0 ]    # Should be: if [ $n -gt 0 ]

    then

3   if [ $n == 5 ]   # Should be: if [ $n -eq 5 ]

    then

4   n++   # Should be: n=`expr $n + 1`

5   if [ "$name" == "Tom" ]      # Should be: if [ $name = "Tom" ]



(csh/tcsh)

    set n = 5; set name = "Tom"

6   if ( $n =< 5 ) then          # Should be: if ( $n <= 5 ) then

7   if ( $n == 5 && <  6 ) then  # Should be: if ( $n == 5 && $n < 6)

8   if ( $name == [Tt]om ) then  # Should be: if ($name =~ [Tt]om )



(ksh)

    name="Tom"

    n=5

9   if [ $name == [Tt]om ]      # Should be: if [[ $name == [Tt]om ]][a]

10  [[ n+=5 ]]  # Should be: (( n+=5 ))

EXPLANATION

  1. In the Bourne shell, the variable n is assigned 5.

  2. The [ bracket is a symbol for the test command. The test command does not use > for greater than, but instead, uses �gt for the relational operator.

  3. The double equal sign is not a valid equality operator for the test command. The operator that should be used is �eq.

  4. The Bourne shell does not support arithmetic operations.

  5. The test command does not use == for equality testing; it uses a single = for string testing and �eq for numeric testing.

  6. The csh/tcsh relational operator should be <=. Misusing relational operators causes a syntax error in all shells.

  7. The expression on the right-hand side of the logical && is incomplete.

  8. The csh/tcsh shells use =~ when evaluating strings containing wildcards. The error in this example would be No match.

  9. The single bracket type of testing does not support the == sign. Bash and ksh use the [[ test command to test expressions containing wildcards. The double equal sign, rather than the single equal sign, is used for testing string equality. (Only versions of ksh newer than ksh88 support the == sign. Earlier versions require the single = for string testing.)

  10. The [[ test command is used with string expressions; the (( let command is used for numeric expressions.

Quoting Errors

Misused quotes are such a common cause for error in shell scripts that a whole section has been devoted to quoting. (See «What You Should Know About Quotes» on page 985.) Quotes are often called the «bane of shell programmers» or the «quotes from hell.» There are three types of quotes: single quotes, double quotes, and backquotes. Single and double quotes surround strings of text to protect certain characters from interpretation, whereas backquotes are used for command substitution. Although we have discussed quotes in previous chapters, the next few sections will focus on how to use them properly to avoid errors.

Quoting Metacharacters

A problem directly related to quoting is the misuse of metacharacters. We’ve already discussed two kinds of metacharacters: shell metacharacters and regular expression metacharacters used with vi, grep, sed, awk, and utility programs other than the shell. (See Chapter 3, «Regular Expressions and Pattern Matching,» on page 67.) Unquoted metacharacters will be interpreted by the shell to mean file matching, and unquoted regular expression metacharacters may cause programs like grep, sed, and nawk to break down. In the following example, the * is used by grep to represent zero or more of the letter «b» and the * is used by the shell to match all filenames starting with an «f». The shell always evaluates the command line before executing the command. Because grep’s * is not quoted, the shell will try to evaluate it, causing an error.

grep ab*c  f*

To fix the problem, quotes are used:

grep 'ab*c'  f*

Now when the shell parses the command line, it will not evaluate the characters within the quotes.

Quotes must be matched. Most shells will send an error message when they realize that there are unmatched quotes. The Bourne shell, on the other hand, parses an entire script file before reporting a problem, which is usually «unexpected end of file,» hardly a big help when the same error message is displayed for a number of other problems.

In order to really achieve expertise in shell scripting, it is imperative to get a good understanding of the quoting mechanism.

Example 15.9.
#! /bin/csh

1   echo I don't understand you.   # Unmatched single quote



    (Output)

2   Unmatched '

----------------------------------------

    #! /bin/csh

3   echo Gotta light?   # Unprotected wildcard



(Output)

4   echo: No match

----------------------------------

    #!/bin/csh

5   set name = "Steve"

6   echo 'Hello $name.'     # Variable not interpreted



(Output)

Hello $name

EXPLANATION

  1. Quotes must be matched. The single quote in don’t causes an error. To fix the problem, the string can be enclosed in double quotes or the single quote can be preceded by a backslash, as don’t.

  2. The C shell displays its error message for a mismatched single quote.

  3. The shell metacharacter, ?, is used to match for single character filenames. There is not a file in the directory spelled light and followed by a single character.

  4. The C shell complains that there is No match for that metacharacter. To fix the problem, the string should be enclosed in either single or double quotes or the question mark should be preceded by a backslash, as ‘Gotta light?’ or light?

  5. The string «Steve» is assigned to a variable.

  6. The string is enclosed in single quotes. The characters within the single quotes are treated literally (i.e., the variable will not be interpreted). To fix the problem, the string should be enclosed in double qutoes or no quotes at all, as «Hello $name.»

What You Should Know About Quotes

Quotes are so inherently part of shell scripting that this section is provided to clarify their use in all the shells. If you are regularly getting quoting syntax errors, study this section to be sure you know how to use them, especially if your script contains commands like grep, sed, and awk.

The Backslash
  1. Precedes a character and escapes that character

  2. Same as putting single quotes around one character

Single Quotes
  1. Must be matched

  2. Protect all metacharacters from interpretation except the following:

    1. Itself

    2. Exclamation point (csh only)

    3. Backslash

Table 15.1. Proper Single Quoting Examples

C/TC Shells

Bourne/Bash Shells

Korn Shell

echo '$*&><?'

$*&><?

echo '$*&!><?'

$*&!><?

print '$*&!><?'

$*&!><?

(C)

echo 'I need $5.00!'

I need $5.00!

echo 'I need $5.00!'

I need $5.00!

print ‘I need $5.00!’

(TC)’

echo ‘I need $5.00!

   
echo 'She cried, "Help"'

She cried, "Help"

echo 'She cried,"Help"'

She cried, "Help"

print 'She cried, "Help"'

She cried, "Help"

echo ‘\\’

echo ‘\\’

print ‘\\’

\\

(Bourne) \

(Bash) \\

\

Double Quotes
  1. Must be matched

  2. Protect all metacharacters from interpretation except the following:

    1. Itself

    2. Exclamation point (csh only)

    3. $ used for variable substitution

    4. ` ` Backquotes for command substitution

Table 15.2. Proper Double Quoting Examples

C Shell

Bourne Shell

Korn Shell

echo «Hello $LOGNAME!»

echo «Hello $LOGNAME!»

print «Hello $LOGNAME!»

echo «I don’t care»

echo «I don’t care»

print «I don’t care»

echo «The date is ‘date'»

echo «The date is ‘date'»

print «The date is $(date)»

echo «\\»

echo «\\»

print «\\»

\\

Backquotes

Backquotes are used in shell programs for command substitution. They are unrelated to single and double quotes, but often the source of problems. For example, when copying a shell script, if the backquotes are replaced with single quotes (merely by misreading the code), the program will no longer work.[1]

[1] In the production of this type of book, it is very easy to mistake backquotes for single quotes!

Example 15.10.
#!/bin/sh

1   now=`date`

2   echo Today is $now

3   echo "You have `ls|wc -l` files in this directory"

4   echo 'You have `ls|wc -l` files in this directory'



(Output)

2   Today is Mon Jul 5 10:24:06 PST 2004

3   You have 33 files in this directory

4   You have `ls|wc -l` files in this directory

EXPLANATION

  1. The variable now is assigned to the output of the UNIX/Linux date command. (For the T/TC shell: set now = `date`.) The backquotes cause command substitution. The backquote is normally found under the tilde (~) on your keyboard.

  2. The value of variable now is displayed with the current date.

  3. The backquotes surround a UNIX/Linux pipe. The output of ls is piped to wc �l. The result is to count the number of files listed in this directory. Double quotes around the string will not interfere with command substitution. The output is embedded in the string and printed.

  4. By enclosing the string in single quotes, the backquotes are not interpreted, but treated as literal characters.

Combining Quotes

Combining quotes can be a major trick. This next section will guide you through the steps for successfull quoting. We will demonstrate how to embed a shell variable in the awk command line and have the shell expand the variable without interfering with awk’s field designators, $1 and $2.

Setting the Shell Variable
name="Jacob Savage"    (Bourne and Korn shells)

set name = "Jacob Savage"  (C shell)



(The line from the datafile)

Jacob Savage:408-298-7732:934 La Barbara Dr. , San Jose, CA:02/27/78:500000



(The nawk command line)

nawk -F: '$1 ~ /^'"$name"'/{print $2}'  datafile



(Output)

408-298-7732

Try this example:

  1. Test your knowledge of the UNIX/Linux command at the command line before plugging in any shell variables.

    nawk -F: '$1 ~ /^Jacob Savage/{print $2}' filename
    
    
    
    (Output)
    
    408-298-7732
    
    

  2. Plug in the shell variable without changing anything else. Leave all quotes as they were.

    nawk -F: '$1 ~ /^$name/{print $2}' datafile
    
    

    Starting at the left-hand side of the awk command leave the first quote as is; right before the shell dollar sign in $name, place another single quote. Now the first quote is matched and all text within these two quotes is protected from shell interference. The variable is exposed. Now put another single quote right after the e in $name. This starts another matched set of single quotes ending after awk’s closing curly brace. Everything within this set of quotes is also protected from shell interpretation.

  3. Enclose the shell variable in a set of double quotes. This allows the variable to be expanded but the value of the variable will be treated as single string if it contains whitespace. The whitespace must be protected so that the command line is parsed properly.

    Count the number of quotes. There should be an even number of single quotes and an even number of double quotes.

Here’s another example:

oldname="Ellie Main"

newname="Eleanor Quigley"

  1. Make sure the command works.

    nawk -F: '/^Ellie Main/{$1="Eleanor Quigley"; print $0}' datafile
    
    

  2. Plug in the variables.

    nawk -F: '/^$oldname/{$1="$newname"; print $0}' datafile
    
    

  3. Play the quoting game. Starting at the first single quote at the left, move across the line until you come to the variable $oldname and place another single quote just before the dollar sign. Put another single quote right after the last letter in the variable name.

    Now move to the right and place another single quote right before the dollar sign in $newname. Put another single quote after the last character in $newname.

  4. Count the number of single quotes. If the number of single quotes is an even number, each quote has a matching quote. If not, you have forgotten a step.

  5. Enclose each of the shell variables in double quotes. The double quotes are placed snugly around the shell variable.

Problems with the here document

The here document, used primarily for creating menus in shell scripts, is often a source of error. The problem is usually found with the user-defined terminator that ends the here document. There can be no space around the terminator. All shells are strict about this rule, although the Bourne, Bash, and Korn shells allow you to use tabs under certain conditions. See the following example.

Example 15.11.
#! /bin/ksh

    print "Do you want to see the menu?"

    read answer

    if [[ $answer = y ]]

    then

1       cat << EOF           <-- No space after user-defined terminator

        1) Steak and eggs

        2) Fruit and yogurt

        3) Pie and icecream

2       EOF                  <-- User-defined terminator cannot

                                 have spaces surrounding it

        print "Pick one "

        read choice

        case "$choice" in

             1) print "Cholesterol"

                  ;;

             2) print "Dieter"

                  ;;

             3) print "Sweet tooth"

                  ;;

        esac

    else

        print "Later alligator!"

    fi



(Output)

file: line 6: here document 'EOF' unclosed

or

file: line 6: syntax error: unexpected end of file (bash)

EXPLANATION

  1. This is the start of a here document. The cat command is followed by << and a user-defined terminator, in this case, EOF. The lines following the terminator are used as input to the cat command, producing a menu of choices on the screen. The input stops when the terminator is reached on line 2.

  2. The terminator on line 2 must exactly match the one on line 1 or the here document will not end. In addition, the final terminator cannot be surrounded by any space. The well-meaning programmer tried to indent the script for better readability, but, in this case indenting the EOF on line 2 causes a syntax error. The solution is to move the terminating EOF to the far left-hand margin and make sure there is no space surrounding it. The bash/ksh/sh shells allow one other fix, which is to put a dash after the << symbol: cat <<� EOF . This allows you to use tabs (and only tabs) to indent the final terminator on line 2.

File-Testing Errors

If you are using external files in a script, it is best to check certain properties of the files before using them, such as their existence, whether they are readable or writable, have any data, are a symbolic link, and so forth. The file tests are quite similar for each shell, but the test for file existence varies. For example, the C, TC, and Bash shells use the �e switch to check if a file exists, the Korn shell uses the �a switch, and the Bourne shell uses the �f switch. With the exception of the TC shell, the file-testing switches cannot be bound together, such as �rw for read and write. Instead a single file-testing switch precedes the filename. An example of a C shell test for a readable, writable, and executable file would be if (�r filename && �w filename && �x filename). An example for a TC shell test would be if (�rwx filename).

Checking for File Existence in the Five Shells

The following error message was generated before file testing was performed in a script. The file called db did not exist.

grep: db: cannot open [No such file or directory]

The following example demonstrates how to fix this problem for each of the five shells.

Example 15.12.
(csh/tcsh)

set filedb = db

if ( ! -e  $filedb ) then

  echo "$filedb does not exist"

  exit 1

endif



(sh)

filedb=db

if [ ! -f  $filedb ]

then

  echo "$filedb does not exist"

  exit 1

fi



(ksh)

filedb=db

if [[ ! -a  $filedb ]]

then

  print "$filedb does not exist"

  exit 1

fi



(bash)

filedb=db

if [[ ! -e  $filedb ]]

then

  echo "$filedb does not exist"

  exit 1

fi

15.4.3 Common Error Messages from the Big 5 Shells

There are a number of different types of syntax errors that will be reported by the shell when you run a script. Each shell reports these errors by sending a message to standard error, and the messages vary from shell to shell. The C shell, for example, is very verbose, and reports errors such as unmatched quotes and undefined variables on the same line where the error occurred, whereas the Bourne shell error messages are sparse and quite cryptic. It is often very hard to debug a Bourne shell script because the error is not reported at all until the script has been completely parsed, and when you get the error message, it may not tell you anything to help you understand your erring ways.

Because each of the shells has its own style of error reporting, Tables 15.3 through 15.6 illustrate the most common syntax errors, the probable cause, what the error message means, and a simple fix.

Table 15.3. Common C/TC Shell Error Messages

Error Message

What Caused It

What It Means

How to Fix It

«: Event not found.

echo «Wow!»

The exclamation mark (history character) must be escaped. Quotes will not protect it.

echo «Wow!»

@: Badly formed number

set n = 5.6; @ n++;

@ n = 3+4

Arithmetic can be performed only on whole numbers and there must be space surrounding arithmetic operators.

set n = 5; @ n++;

@ n = 3 + 4

@n++: Command not found

@n++

The @ sign must be followed by a space.

@ n++

Ambiguous.

`date`

The backquotes are used for command substitution when the output of a command is being assigned to a variable or is part of a string. If the command is on a line by itself, it should not be enclosed in backquotes. Tcsh will give the error Fri: Command not found.

echo The date is `date`

or

set d = `date`

Bad : modifier in $ (f).

echo $cwd:f

The :f is an invalid pathname expansion modifier.

echo $cwd:t

or

$cwd:h

etc.

Badly placed ()’s.

echo (abc)

The parentheses are used to start a subshell. The whole command should be placed in () or the string should be quoted.

( echo abc )

or

echo «(abc)»

echo: No match.

echo How are you?

The question mark is a shell metacharacter used in filename expansion. It represents one character in a filename. The shell will match for a file named you followed by a single character. Because there isn’t a file by that name, the error No match is displayed.

echo "How are you?" or

echo 'How are you?'

or

echo How are you?

filex: File exists.

sort filex > temp

The noclobber variable has been set and the temp file exists. noclobber will not let you overwrite an existing file.

sort filex > temp1

(use a different file for output)

or

unset noclobber

or

sort filex >! temp

(override noclobber)

fruit: Subscript out of range

echo $fruit[3]

The array fruit does not have three elements.

set fruit = ( apples pears plums )

if : Empty if

if ( $x > $y )

The if expression is incomplete. The then is missing.

if ( $x > $y ) then

if : Expression Syntax

if ( $x = $y ) then

The if equality operator should be ==.

if ( $x == $y ) then

if : Expression Syntax

set name = "Joe Doe"

if ( $name == "Joe Doe" ) then

The variable name on the left-hand side of the == sign should be double quoted.

if ( «$name» == «Joe Doe» ) then

if: Expression syntax.

if ( grep john filex ) then

When evaluating a command, curly braces should surround the command, not parentheses.

if { grep john filex } then

Invalid null command

echo «hi» &> temp

The redirection operator is backwards. Should be >&.

echo «hi» >& temp

Missing }.

if {grep john filex} then

The curly braces must be surrounded by space.

if { grep john filex } then

set: Syntax error

set name= «Tom»

The equal sign must have space on either side, or no space at all.

set name = «Tom»

or

set name=»Tom»

set: Syntax error

set name.1 = «Tom»

A period is not a valid character in a variable name.

set name1 = «Tom»

set: Syntax error

set file-text = «foo1»

The dash is an illegal character in the variable name.

set file_text = «foo1»

shift: No more words

shift fruit

The shift command removes the leftmost word in an array. The error is caused because the array, fruit, has no more word elements. You cannot shift an empty array.

set fruit = ( apples pears plums )

then: then/endif not found.

if ( $x > $y ) then

   statements

   statements

The if expression is incomplete. The endif is missing.

if ( $x > $y ) then

   statements

endif

Too many (‘s

if ( $x == $y && ( $x != 3 ) then

The expression has unbalanced parentheses. Either add one to the right-hand side or remove the ( after the &&.

if ( $x == $y && ( $x != 3 )) then

or

if ( $x == $y && $x != 3 ) then

top: label not found.

goto top

The goto command is looking for a label called top that should be on a line by itself somewhere in the program. Either that, or the label is there but is spelled differently.

top:

goto top

Undefined variable

echo $name

The variable name has never been set.

set name; set name = "John";

set name = ""

Unmatched «.

echo She said, «Hello

The double quote must be matched on the same line.

echo ‘She said, «Hello»‘

Unmatched ‘.

echo I don’t care

The single quote must be matched on the same line.

echo «I don’t care»

or

echo I don’t care

while: Expression syntax.

while ( $n =< 5 )

The wrong operator was used. It should be <=.

while ( $n <= 5 )

Table 15.6. Common Bash Shell Error Messages

Error Message

What Caused It

What It Means

How to Fix It

bash: syntax error: ‘» unexpected EOF while looking for matching ‘»

echo I don’t care

The single quote is unmatched in the script.

echo «I don’t care»

bash: syntax error: ‘»‘ unexpected EOF while looking for matching ‘»

print She said «Hello

The double quote is unmatched in the script.

print She said «Hello»

[Blank line] No error message, no output

echo $name

or

echo ${fruit[5]}

The variable doesn’t exist or is empty.

name=»some value» or use set -u to catch any variables that have not been sent. The message ksh: name: paramter not set will be sent to stderr.

bash: name: command not found

name = «Tom»

There cannot be any space on either side of the equal sign.

name=»Tom»

bash: 6.5: syntax error in expression (error token is «.5»)

declare -i num; num=6.5

Only integer values can be assigned to variable num.

num=6

bash: [ellie: command not found

if [$USER = «ellie»] ; then

or

if [[$USER = «ellie» ]] ; then

There must be a space after the [ or [[.

if [ $USER = «ellie» ] ; then

or

if [[ $USER = «ellie» ]] ; then

bash: syntax error near unexpected token ‘fi’

if [ $USER = «ellie» ] then

The then should be on the next line or preceded by a semicolon.

if [ $USER = «ellie» ] ; then

or

if [ $USER = "ellie" ]

then

bash: syntax error in conditional expression

if [[ $name = John Doe ]] ; then

Word splitting is not performed on the variable on the left-hand side of the =, but the string on the right-hand side must be quoted.

if [[ $name == «John Doe» ]] ; then

[: fred: binary operator expected

if [ grep fred /etc/passwd ] ; then

The grep command should not be surrounded by square brackets or any other symbols. The brackets are used only when testing expressions. The [ is a test operator.

if grep fred /etc/passwd ; then

./file: line 5: syntax error near unexpected token blue)

color="blue"

case $color 

The case command is missing the in keyword.

case $color in

.filename: line2:syntax error at line 6: «)» unexpected.

case $color in

  blue)

     echo "blue"

  red)

     echo "red"

       ;;

esac

The case statement is not terminated with ;; after echo «blue».

case $color in

  blue)

    echo "blue"

      ;;

  red)

    echo "red"

      ;;

esac

bash: shift: bad non-numeric arg ‘fruit’

declare -a fruit=(apples pears peaches);

shift fruit

The shift built-in command cannot shift an array. It is used only to shift positional parameters.

set apples pears peaches; shift

[: too many arguments

name="John Doe";

if [ $name = Joe ]

The variable name should be double quoted in the test expression. There can be only one string on the left-hand side of the = test operator unless it is quoted. The other alternative is to use the compound test operator [[ ]]. Words will not be split when using this operator.

if [ «$name» = Joe ]

or

if [[ $name == Joe ]]

bash: syntax error near unexpected token ‘{echo’

function fun {echo «hi»}

There should be space surrounding the curly braces in the definition for the function fun() and a semicolon to terminate the function statement.

function fun { echo «hi»; }

bash: filex: cannot overwrite existing file

sort filex > temp

The noclobber variable has been set and the temp file exists. noclobber will not let you overwrite an existing file.

sort filex > temp1

(use a different file for output)

or

set +o noclobber or sort filex >| temp

(override noclobber)

bash: trap: 500: not a signal specification

trap ‘rm tmp*’ 500

The number 500 is an illegal signal. Normally signals 2 or 3 will be trapped in a shell script. 2 is for Ctrl-C and 3 is for Ctrl-. Both signals cause the program named after the trap command to be terminated.

trap ‘rm tmp*‘ 2

Common C/TC Shell Error Messages

Table 15.3 lists commonly found C shell error messages. Because the TC shell mimics the the C shell errors so closely, the chart serves to address both shells.

Common Bourne Shell Error Messages

Table 15.4 lists commonly found Bourne shell error messages.

Table 15.4. Common Bourne Shell Error Messages

Error Message

What Caused It

What It Means

How to Fix It

./file: line 5: syntax error near unexpected token blue)

color="blue"

case $color

The case command is missing the in keyword.

case $color in

[Blank line] The shell produces a blank line, no error message.

echo $name

The variable doesn’t exist or is empty.

name=»some value»;

[ellie: not found

if [$USER = «ellie»] ; then

There must be a space after the [.

if [ $USER = «ellie» ] ; then

answer: not found

answer = «yes»

There cannot be any space on either side of the equal sign.

answer=»yes»

cannot shift

shift 2

The shift built-in command is used to shift positional parameters to the left. If there are not at least two positional parameters, the shift will fail.

set apples pears peaches; shift 2 (apples and pears will be shifted from the list)

name: is read only

name="Tom";

readonly name;

name="Dan"

The variable was set to be a readonly variable. It cannot be redefined or unset.

name2=»Dan»

or

exit shell

name: parameter not set

echo $name

set -u has been set. With this option to the set command, undefined variables are flagged.

name=»some value»;

name.1=Tom: not found

name.1=»Tom»

A period is not valid in a variable name.

name1=»Tom»

syntax error at line 7 ‘fi’ unexpected

if [ $USER = "ellie" ]

  echo "hi"

fi

There must be then after the expression.

if [ $USER = "ellie" ]

then

  echo "hi"

fi

syntax error: `{‘

fun() {echo «hi»;}

There should be space surrounding the curly braces in the definition for the function, fun().

fun() { echo «hi»; }

syntax error: ‘done’ unexpected

while  [ $n < 5 ]

  statements

done

The while is missing the do keyword.

while [ $n -lt 5 ]

do

  statements

done

syntax error: ‘fi’ unexpected»

if [ $USER = «ellie ] then

The then should be on the next line or preceded by a semicolon.

if [  $USER = "ellie" ]

then

or

if [ $USER = «ellie» ]; then

test: argument expected

if [ 25 >= 24 ] ; then

The >= is not a valid test operator. Should be -ge .

if [ 25 -ge 24 ]; then

test: unknown operator

if [ grep $USER /etc/passwd ] ; then

The grep command should not be surrounded by square brackets or any other symbols. The brackets are used only when testing expressions. The [ is a test operator.

if grep $USER /etc/passwd ; then

test: unknown operator Doe

name="John Doe";

if [ $name = Joe ]

The variable, name, should be double quoted in the test expression. There can be only one string on the left-hand side of the = operator unless it is quoted.

if [ «$name» = Joe ]

trap: bad trap

trap ‘rm tmp*’ 500

The number 500 is an illegal signal. Normally signals 2 or 3 will be trapped in a shell script. 2 is for Ctrl-C and 3 is for Ctrl-. Both signals cause the program named after the trap command to be terminated.

trap ‘rm tmp*’ 2

unexpected EOF

or

unexpected end of file

echo «hi

The double quote is unmatched in the script. The Bourne shell will search until the end of the file for the matching quote. You may not receive an error message, but program output will be unexpected. The unexpected EOF error will occur if the case or looping commands are not ended with their respective keywords, esac and done.

echo «hi»

Common Korn Shell Error Messages

Table 15.5 lists commonly found Korn shell error messages.

Table 15.5. Common Korn Shell Error Messages

Error Message

What Caused It

What It Means

How to Fix It

./file: line 5: syntax error near unexpected token blue)

case $color

  blue)

     ...

The case command is missing the in keyword in a script.

case "$color" in

  blue)

    ...

.filename: line2:syntax error at line 6: «)» unexpected .

case $color in

  blue)

    echo "blue"

  red)

    echo "red"

      ;;

  esac

The first case statement is not terminated with ;; after echo «blue».

case $color in

  blue)

    echo "blue"

      ;;

  red)

    echo "red"

      ;;

esac

[Blank line ]

echo $name

or

echo ${fruit[5]}

The variable doesn’t exist or is empty.

name=»some value»

file: line2: syntax error at line 6: ‘done’ unexpected

while  (( $n < 5 ))

  statements

done

The while is missing the do keyword.

while (( n < 5 ))

do

  statements

done

file: syntax error at line 3: ‘» unmatched

print I don’t care

The single quote is unmatched in the script. It should be preceded by a backslash or enclosed in double quotes.

echo I don’t care

or

echo «I don’t care»

file: syntax error at line 3: ‘»‘ unmatched

print She said «Hello

The double quote is unmatched in the script.

print She said «Hello»

ksh: [: Doe: unknown operator

name="John Doe"

if [ $name = Joe ]; then

The variable, name, should be double quoted in the test expression. There can be only one string on the left-hand side of the = test operator unless it is quoted. The other alternative is to use the compound test operator [[ ]]. Words will not be split when using this operator.

if [ «$name» = Joe ]; then

or

if [[ $name = Joe ]]; then

ksh: [ellie: not found

if [$USER =  "ellie"] ; then

if [[$USER = "ellie" ]] ; then

There must be a space after the [ or [[.

if [ $USER = «ellie» ] ; then

or

if [[ $USER = «ellie» ]] ; then

ksh: apples: bad number

set -A fruit apples pears peaches; shift fruit

The shift built-in command cannot shift an array. It is used only to shift positional parameters.

set apples pears peaches; shift

-ksh: file.txt=foo1: not found

file.txt=»foo1″

The variable cannot have a period in its name.

file_txt=»foo1″

ksh: filex: file already exists.

sort filex > temp

The noclobber variable has been set and the temp file exists. noclobber will not let you overwrite an existing file.

sort filex > temp1

(use a different file for output)

or

set +o noclobber or sort filex > temp

(override noclobber)

ksh: fred: unknown test operator

if [ grep fred /etc/passwd ] ; then

The grep command should not be surrounded by square brackets or any other symbols. The brackets are used only when testing expressions. The [ is a test operator.

if grep fred /etc/passwd ; then

ksh: name: not found

name = «Tom»

There cannot be any space on either side of the equal sign.

name=»Tom»

ksh: shift: bad number

shift 2

The shift built-in command is used to shift positional parameters to the left. If there are not at least two positional parameters, the shift will fail.

set apples pears peaches;

shift 2

(apples and pears will be shifted from the list)

ksh: syntax error: ‘{echo’ not expected

function fun {echo «hi»}

There should be space surrounding the curly braces in the definition for the function fun() and a semicolon to terminate the function statement.

function fun { echo «hi»; }

ksh: syntax error: ‘Doe’ unexpected

if [[ $name = John Doe ]]

Word splitting is not performed on the variable on the left-hand side of the =, but the string on the right-hand side must be quoted.

if [[ $name = «John Doe» ]]

ksh: syntax error: ‘fi’ unexpected»

if [ $USER = «ellie ] then

The then should be on the next line or preceded by a semicolon.

if [ $USER = "ellie" ]

then

or

if [ $USER = «ellie» ] ; then

ksh: syntax error: ‘then’ unexpected

if (( n==5 && (n>3 || n<7 ))

The parentheses enclosing the second expression are not matched.

if (( n==5 && (n>3 || n<7) ))

ksh: trap: 500: bad trap [a]

trap ‘rm tmp*‘ 500

The number 500 is an illegal signal. Normally signals 2 or 3 will be trapped in a shell script. 2 is for Ctrl-C and 3 is for Ctrl-. Both signals cause the program named after the trap command to be terminated.

trap ‘rm tmp*‘ 2

[a] This error occurs with public domain Korn shell, but Korn shell 88 (Solaris) produces no output.

Common Bash Error Messages

Table 15.6 lists commonly found Bash shell error messages.

15.4.4 Logic Errors and Robustness

Logic errors are hard to find because they do not necessarily cause an error message to be displayed, but cause the program to behave in an unexpected way. Such errors might be the misuse of a relational, equality, or logical operator, branching incorrectly in a set of nested conditional statements, or going into an infinite loop. Robustness refers to errors that should have been spotted if sufficient error checking had been performed, such as checking for bad user input, insufficient arguments, or null values in variables.

Logical Operator Errors

Example 15.13 shows a logical operator error and a possible fix for it.

Example 15.13.
    #!/bin/csh

1   echo -n "Enter -n your grade: "

    set grade = $<

2   if ( $grade < 0 && $grade > 100 ) then

3       echo Illegal grade.    # This line will never be executed

        exit 1

    endif

4   echo "This line will always be executed."



(Output)

Enter your grade: -44

This line will always be executed.



Enter your grade: 234

This line will always be executed.

Enter your grade



------------------Possible Fix----------------



if ( $grade < 0 || $grade > 100 ) then

EXPLANATION

  1. The user is asked for input. The input is assigned to the variable grade.

  2. With the logical AND (&&) both expressions must be true in order to enter the if block on line 3. If both expressions are true, the user would have to have entered a grade that is both lower than 0 and also greater than 100. How could that be possible? The || OR operator should be used. Then only one of the conditions must be true.

  3. This line will never be printed.

  4. Because line 2 will never be true, this statement will always be executed.

Relational Operator Errors

Example 15.14 shows a relational operator error and a possible fix for it.

Example 15.14.
    #!/bin/csh

    echo -n "Please enter your age "

    set age = $<



1   if ( $age > 12 && $age < 19 ) then

        echo A teenager            # What if you enter 20?

2   else if ( $age > 20 && $age < 30 ) then

        echo A young adult

3    else if ( $age >= 30 ) then    # What if the user enters 125?

        echo Moving on in years

    else

4       echo "Invalid input"

    endif



(Output)

Please enter your age  20

Invalid input



Please enter your age  125

Moving on in years



------------------Possible Fix----------------



if ( $age > 12 && $age <= 19 ) then

    echo A teenager

else if ( $age >= 20 && $age < 30 ) then

     echo A young adult

else if ( $age >= 30  && $age < 90 ) then

   echo Moving on in years

else if ( $age <=12 ) then

   echo still a kid

else

   echo "Invalid input"

endif

EXPLANATION

  1. This expression tests for an age between 13 and 18. To check for ages between 13 and 20, the right-hand expression can be changed in two ways: ( $age <= 19 ) to include 19, or ( $age < 20 ).

  2. If the age is 19, the program will always go to line 3. This expression tests for ages between 21 and 29. We need to include 20 in this expression. If the user enters 19 or 20, the program prints Invalid input.

  3. This expression tests for any age older than 29. There is no range here. Unless the user can be infinitely old, the expression needs to include the outside range.

  4. Invalid inputs are 19, 20, and any number below 13.

Branching Errors

Example 15.15 shows a branching error and a possible fix for it.

Example 15.15.
1   set ch = "c"

2   if ( $ch == "a" ) then

3       echo $ch

4       if ( $ch == "b" ) then       # This "if" is never evaluated

            echo $ch

5   else

6       echo $ch

7   endif

8   endif



(Output)

<no output>



------------------Possible Fix----------------



set ch = "c"

if ( $ch == "a" ) then

   echo $ch

else if ( $ch == "b" ) then

          echo $ch

else

     echo $ch

endif

EXPLANATION

  1. The variable ch is assigned the letter c.

  2. If the value of $ch is an a, then lines 3 to 5 are executed.

  3. If the value of $ch is an a, the value of $ch is printed, and the program continues with the nested if on line 4. This statement will never get executed unless $ch was an a.

  4. If the value of $ch were an a, then it could not be a b and line 6 would be executed.

  5. This else should be indented so that it is placed under the inner if. The else goes with the innermost if on line 4.

  6. This line will be executed only if $ch is an a.

  7. This endif goes with the innermost if on line 4.

  8. This endif goes with the outer if on line 2.

Exit Status with an if Conditional

When the if command is evaluating the success or failure of a command, it checks the exit status of that command. If the exit status is 0, the command was successful and if nonzero the command failed in some way. If you are not sure of what exit status a command returns, you should check before using it, or your program may not perform as expected. Consider the following example. The awk, sed, and grep commands are all able to use regular expressions for searches in a pattern, but grep is the only one of the three commands that reports a nonzero exit status if it cannot find the search pattern. The sed and awk programs will return 0, whether the pattern is found or not. Therefore, neither of these programs would be of any use after an if condition, because the condition would always be true.

Example 15.16.
  #!/bin/sh

1   name="Fred Fardbuckle"

2   if grep "$name" db > /dev/null 2>&1

    then

3       echo Found $name

    else

4       echo "Didn't find $name"        # Fred is not in the db file

    fi

5   if awk "/$name/" db > /dev/null 2>&1

    then

6       echo Found $name

    else

        echo "Didn't find $name"

    fi

7   if sed -n "/$name/p" db > /dev/null 2>&1

    then

8       echo Found $name

    else

        echo "Didn't find $name"

    fi



(Output)

4  grep: Didn't find Fred Fardbuckle

6  awk: Found Fred Fardbuckle

8  sed: Found Fred Fardbuckle



------------------------Possible Fix--------------------------



Check the exit status of the command before using it.



      awk "/$name/" db

      echo $? (bash, sh, ksh)

      echo $status (tcsh, csh, bash)

EXPLANATION

Here we see that awk, nawk, and gawk always return an exit status of 0, unless the command statements are incorrect. grep returns an exit status of 0 if its search is successful, and a nonzero integer if it cannot find the pattern in the file or if the file does not exist.

Lacking Robustness

A program is robust if it can handle illegal input and other unexpected situations in a reasonable way. For example, if a program is expecting numeric data, then it must be able to check to see if that’s what it got, and print an error message and ignore the bad input. Another example of robustness would be if the script is going to extract data from an external file, but the external file doesn’t exist or does not have read permissions. The robust program would use file testing to check for the existence of the file before trying to read from it.

Example 15.17 shows how to check for null input.

Example 15.17.
#!/bin/csh

# Program should check for null input -- T and TC shells



1   echo -n "Enter your name: "

        set name = $<       # If user enters nothing, program will hang

2   if { grep "$name" db >& /dev/null } then

        echo Found name

    endif



(Output)

Enter your name:  Ellie

Found name



Enter your name:

     <program prints every line in the file Found name>



---------------------Possible Fix-------------------------------------



   echo -n "Enter your name: "

   set name = $<    # If user enters nothing, program will hang

3   while ( $name == "" )

      echo "Error: you did not enter anything."

      echo -n "Please enter your name"

      set name = $<

   end

      <program continues here>

EXPLANATION

  1. The user is asked for input. If he or she presses the Enter key, the variable, name, will be set to null.

  2. The first time the program runs, the user types something and grep searches in the file for that pattern. The next time, the user presses the Enter key. The variable is set to null, causing the the grep program to search for null. Every line will be printed. Because the errors and output are sent to /dev/null, it is not obvious why the grep is printing the contents of the entire file.

  3. The loop tests for a null value in the variable name. The loop will continue until the user enters something other than pressing Enter. For ksh, bash, and sh, use the correct syntax for a while loop (e.g., while [ $name = » » ] or while [[ $name = » » ]). See specific character for syntax.

Examples 15.18 and 15.19 show how to check for insufficient arguments.

Example 15.18.
    #!/bin/sh

    # Script: renames a file -- Bourne shell



1   if [ $# -lt 2 ]     # Argument checking

2   then

        echo "Usage: $0 file1 file2 " 1>&2

        exit 1

    fi

3   if [ -f $1 ]        # Check for file existence

    then

        mv $1 $2         # Rename file1

        echo $1 has been renamed to $2

   else

        echo "$1 doesn't exist"

        exit 2

    fi



(Output)

$ ./rename file1

Usage: mytest file1 file2

EXPLANATION

  1. If the number of positional parameters (arguments) is less than 2 . . .

  2. . . . the error message is sent to standard error and the program exits. The exit status will be 1, indicating a problem with the program.

  3. The program continues if sufficient arguments are passed in from the command line. Check correct syntax to convert this program to ksh or bash.

Example 15.19.
   #!/bin/csh

   # Script: renames a file -- C/TC shells



1   if ( $#argv < 2 ) then        # Argument checking

2       echo "Usage: $0 file1 file2 "

3       exit 1

    endif

    if ( -e $1 ) then             # Check for file existence

        mv $1 $2                  # Rename file1

        echo $1 has been renamed to $2

    else

        echo "$1 doesn't exist"

        exit 2

    endif



(Output)

% ./rename file1

Usage: mytest file1 file2

Examples 15.20 and 15.21 show how to check for numeric input.

Example 15.20.
(The Script)

    $ cat trap.err

    #!/bin/ksh

    # This trap checks for any command that exits with a nonzero

    # status and then prints the message -- Korn shell



1   trap 'print "You gave me a non�integer. Try again. "' ERR

2   typeset �i number     # Assignment to number must be integer

3   while true

    do

4       print �n "Enter an integer. "

5       read �r number 2> /dev/null

6       if (( $? == 0 ))     # Was an integer read in?

        then                 # Was the exit status zero?



9   if grep ZOMBIE /etc/passwd > /dev/null 2>&1

    then

         :

    else

10       print "$n is $n. So long"

    fi



(The Command Line and Output)

    $ trap.err

4   Enter an integer. hello

1   You gave me a non�integer. Try again.

4   Enter an integer. good�bye

1   You gave me a non�integer. Try again.

4   Enter an integer. \

1   You gave me a non�integer. Try again.

4   Enter an integer. 5

10  $n is 5. So long.



    $ trap.err

4   Enter an integer. 4.5

10  $n is 4. So long.

Example 15.21.
(The Script)

    #!/bin/bash

1   # Scriptname: wholenum

    # Purpose:The expr command tests that the user enters an integer -- Bash shell



    echo "Enter an integer."

    read number

2   if expr "$number" + 0 >& /dev/null

    then

3       :

    else

4        echo "You did not enter an integer value."

         exit 1

5   fi

    Понравилась статья? Поделить с друзьями:
  • Shell notifyicon error 1008
  • Shell infrastructure host как исправить
  • Sheet set error set again
  • Sheet set error roland
  • She wear old jeans at home исправьте ошибки