4

兼容

Zsh在大部分时候是兼容Bash, 是的“大部分时候”
如果你要强求的话,可以在Zsh里执行下面命令

emulate bash

数组

如果在loop里使用了数组,那么脚本在Bash里可以工作,而在Zsh里则不行

arr=("a" "b" "c")
for((i=0; i < ${#arr}; i++))
do 
  echo ${arr[$i]}
done

有两个地方破坏了兼容性:

  • 在for后面应该加一个空格
  • Bash的数组是从0开始的,而Zsh里是从1开始的
    所以如果为了兼容,一个不太好的解决方案就是:

    arr=("z" "a" "b" "c")
    for((i=1; i < ${#arr}; i++))
    do 
    echo ${arr[$i]}
    done

通配符

如果文件sort.txt在下级目录下存在,那么ls */sort.txt是两种shell里都可以工作,但如果不存在的话,Zsh会报zsh:no matches found: */sort.txt
解决方案是使用双引号:

ls "*/sort.txt"

在Bash里globbing失败被作为匹配失败返回,而Zsh是作为语法错误,会使脚本无法继续运行。所以一个方法就是使用eval

if eval "ls *.md" &> /dev/null
then
    :
else
    echo $?
fi

条件比较

这种if语句如下

[[ "1" == "1" ]] echo "equals.";

Bash里工作正常,但Zsh会有zsh: = not found的错误。 为了兼容只能使用一个“=”。

另外,在任何时候都建议使用完整的if语句, 比如

if [[ "$foo" = "" ]];
then
    echo "foo is empty!"
    exit
fi

echo

echo 是Zsh和Bash里的内置命令,它们不兼容
在Bash和Zsh里输入

$ echo \\
\
$echo \\\\
\\

但在Zsh结果不一样

$ echo \\
\
$echo \\\\
\

原因是Zsh在读入里转义一次,输出时又转义一次
所以在Zsh里用了单引号后是下面的结果

$ echo ‘\\’
\
$echo ‘\\\\’
\\

而bash里则原版输出
如果要让Zsh中echo输出是不转义,需要用-E显式地指出

$ echo -E ‘\\’
\\
$echo -E ‘\\\\’
\\\\

分词

echo $args

Bash中会对$args转进来的字符串进行分词(以空格或换行符为分隔符),所以这里echo会收到多个参数。换行符会被吃掉。
为了解决换行符被吃掉的问题,可以把变量名放在双引号中, 这样就可以作为一个字符地串被读到。
在Zsh里,不需要用双引号来保证变量是作为一个字符串传进来。

空语句

在Bash中空语句
:
而在Zsh空语句就是空
所以在上例中, Bash下要写:,而Zsh可以什么都不写

关联数组

$declare -A arr
arr[first] = foo

在Bash中要引用关联数组成员时,需要用

echo ${arr[first]}

而在Zsh中则不需要外面的{}

echo $arr[first]

globbing和关联数组

Zsh里支持使用方括号进行复杂的globbing, 比如foo[bar], 可以表示foob, fooa, foor.
如果它前面有$, 那么$foo[bar]没有异义地表示关联数组,但如果没有的时候有时就会搞错
这时会了阻止glob展开,就需要用单引号'把字符串括起来。
还有一种解决方法是用

alias testglob="noglob testglob"

那么就不会对传给命令testglob的参数做globbing展开

总结

  1. 注意空格和引号
  2. 注意数组index的不同
  3. 使用一个等号,避免使用短的if语句

参考

http://slopjong.de/2012/07/02...
http://www.360doc.com/content...


harriszh
338 声望131 粉丝

做些有趣的事,留些有用的存在