在一次偶然的事件中,我复制了一段EOF代码粘贴到脚本的另一位置,结果脚本就不运行了。后来通过排查发现原来是空格的问题。下面举例说明这个问题。

首先看如下脚本

# vim bb.sh 

#!/bin/bash
echo test
if [ $? -eq 0 ];then
        echo "aa"
else
        cat >aa <<-EOF
        6
        EOF
        echo "bb"
fi
echo $?

# ./bb.sh 

test

aa

0

脚本执行成功,一切正常。

现在我们做两个操作,比较下异同。

操作一:在vim中复制以下代码段粘贴到if的else上方。

        cat >aa <<-EOF
        6
        EOF



完成后代码如下:

#!/bin/bash
echo test
if [ $? -eq 0 ];then
        echo "aa"
        cat >aa <<-EOF
        6
        EOF
else
        cat >aa <<-EOF
        6
        EOF
        echo "bb"
fi
echo $?

# ./bb.sh 

test

aa

0

# cat aa

6

一切执行正常,aa文件也被写入了EOF中的数值6

操作二:我们不用vim的yy命令去复制,而是改用xhell的鼠标复制功能,用鼠标选定这三行,再粘贴到上面的else上方。

wKiom1cLGMySnWBCAAAjFYkvCiI079.png

粘贴后代码如下:

#!/bin/bash
echo test
if [ $? -eq 0 ];then
        echo "aa"
        cat >aa <<-EOF
        6
        EOF
else
        cat >aa <<-EOF
        6
        EOF
        echo "bb"
fi
echo $?

看上去与yy复制的并没有什么不同。

那么我们执行一下看看。

# ./bb.sh 

test

aa

bb

0

得到的结果完全出乎意料,可以看到if命令已经失效了,echo "aa" echo "bb"都被执行了!

# cat aa

        6

        EOF

else

        cat >aa <<-EOF

6

再看输入的aa文件,也不是想要的结果6!而是前后两个EOF之间的字段

wKioL1cLGvXSOBWXAAAfJ2zYSRE755.png


那么这是为什么?

原因就在于空格和tab的问题!

在vim下我们用:set list来显示特殊字符

下图是操作一,即用yy命令复制时的代码图

wKiom1cLHMGxMmsjAAAfKVZpeMQ512.png

下图是操作二,即用鼠标复制时的代码图

wKiom1cLHEnAsNqpAAAfU4lybLk145.png

发现两者的不同没有?

操作一中yy复制的三行和原来的三行格式一样,EOF结尾符前面是^I,即tab字符。

操作二中鼠标复制的三行和原来的三行格式不一样,EOF结尾符前面是空格,不是tab!

结论:

重定向-EOF只会匹配前面以tab开头的EOF结束符,而不会匹配空格开头的EOF,操作二中,由于第一个EOF前面是空格,不会被识别为结束标志,而是被当作一个输入的字符来对待,当遇到第二个EOF时,由于前面是tab键,就被匹配为结束字符,所以也就出现了aa文件中的那一大串字符。