玩bash,得到语法错误

时间:2014-06-16 15:41:49

标签: bash

我正在尝试为Linux / Unix类编写一个简单的bash脚本,并且我不断收到语法错误。甚至我的教授也很快就看不懂了。

非常感谢任何见解!

pattersoncode:~ austen$ ./bash2
./bash2: line 3: if[ =0 ]: command not found
./bash2: line 4: syntax error near unexpected token `then'
./bash2: line 4: `then'
pattersoncode:~ austen$ 

此致

a=6
test $a -eq 6 > b
if[ "$b"="0" ]
then
echo True
else
echo False
fi

2 个答案:

答案 0 :(得分:4)

白色空间在BASH中非常重要。

对不起喊叫,但这需要强调。与其他脚本语言(如Perl或Python)不同,Bash对空白区域非常敏感。例如:

右:

foo="bar"     # No spaces around the equal sign.

错误:

foo = "bar"   # This is a syntax error because of the spaces around the equal sign

右:

if [ "$foo" = "bar" ]   # You need spaces around the equal sign.
then
    ...
fi

错误“:

if [ "$foo"="bar" ]   # Syntax error: You forgot the spaces around the equal sign.
then
    ...
fi

shell不会解释变量。它插入变量。有一个微妙的区别。

在shell执行命令之前,它会运行干扰。它查找环境变量并用它们的值替换它们。 (它也会删除整数并用匹配的文件替换它们。)

例如,这些在Perl中都是有效的:

if ( $foo == $bar ) {

if($foo==$bar) {

if ($foo== $bar) {

那是因为Perl 解释了这一行,因此它将$foo$bar视为变量,即使空格不在那里也是如此。即使$foo$bar为空,也没有问题。 Perl理解您将变量$foo的值与变量$bar的值进行比较。

但是,shell运行方式不同,它插入。在执行if语句之前,shell 删除环境变量,用它们的值替换。然后,只有这样shell才会执行if语句。

if [ $foo = $bar ]

假设$foo$barbanana设置为if [ $foo = $bar ] 时,我们假设{/ 1}}:

shell看到了这个:

$foo

并使用指定的值替换$barif [ = banana ]

if [ x$foo = x$bar ]

这是一个语法错误。你错过了等号左边的值。在较旧的shell脚本中,您将看到如下内容:

if [ x = xbanana ] 

在这种情况下,shell将删除环境变量并用它们的值替换它们:

$foo

这是一个有效的文本比较。这是另一个有趣的事实。想象一下,如果-f等于字符串$bar,而if [ $foo = $bar ] 为空,那么

if [ -f = ]

现在将插值 as:

=

而且,这是有效的。它询问是否存在名为if [ "$foo" = "$bar" ] 的文件。

解决这个问题的方法是始终在变量周围加上引号。这样:

if [ "-f" = "" ]

将插值为:

[

这是一个有效的字符串比较。

顺便说一句,ls /bin/[周围需要空格,因为这不是一些语法,它是一个命令!

执行[,您会看到/bin/test是Unix命令。它与if [ "$foo" = "$bar" ]

相关联

因此:

if test "$foo" = "$bar"

实际上与:

相同
=

而且,这就是为什么你也需要等号周围的空间。 test./bash2: line 3: if[ =0 ]: command not found 命令的参数。

现在,看看你的错误,看看你是否能弄清楚它们的含义:

if[

当然,[不是命令。你忘记了$b周围的空白区域。此外,set -xv没有价值,这就是为什么你在那里看不到它。

您可以做的一件好事是将if添加到您的shell脚本中。这将打开详细调试。您将能够看到shell看到的命令,然后查看shell如何插入该命令。这是捕获错误的好方法。

顺便说一下,if command 命令的实际语法是:

if

then语句运行该命令。如果该命令返回退出代码为零,则该语句被视为true,因此执行if的{​​{1}}部分。这就是[ ... ]的作用。 (记住,我说[是一个命令)。执行[ ... ]测试。如果是,则执行then语句的if部分。否则,else子句(如果存在)。

你会一直在shell脚本中看到这样的东西:

if ! rm  "$foo"
then
    echo "File '$foo' was removed."
else
    echo "Can't remove file '$foo'."
fi

注意我只是运行rm而我正在使用if来测试rm命令是否成功。

对罗嗦的解释感到抱歉。 Shell不是一种普通的脚本语言,除非您了解shell的运行方式,否则很难理解正在发生的事情。使用set -xv启用调试,set +xv启用调试功能。

另外,为了好玩,试试这两个陈述,看看会发生什么:

$ echo *   # No quotes
$ echo "*" # Quotes around the asterisk

答案 1 :(得分:0)

你可以通过许多不同的方式来做到这一点。这只是一个:

#!/bin/bash
a=6
test  $a -eq 6
b=$?                # Here you store the error exit code
if [ "$b" = "0" ]
  then
    echo True
  else
    echo False
fi

### short and cryptic bash version  :-) 
aa=7
test  $aa -eq 7  && echo True2 || echo False

bash中可以用简短的方式编写构造

 if test_condition
   then   
       ...   
   else  
       ...  
   fi


test_condition && ... || ...

其中&&扮演then角色,||扮演else角色。