兼容
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展开
总结
- 注意空格和引号
- 注意数组index的不同
- 使用一个行号,避免使用短的if语句
参考
http://slopjong.de/2012/07/02…
http://www.360doc.com/content…