我正在遵循Linux shell编程指南来提高我对shell的熟练程度。今天,我到达了嵌套循环的部分。
以下脚本在终端上打印棋盘。
for (( i = 1; i <= 9; i++ )) ### Outer for loop ###
do
for (( j = 1 ; j <= 9; j++ )) ### Inner for loop ###
do
tot=`expr $i + $j`
tmp=`expr $tot % 2`
if [ $tmp -eq 0 ]; then
echo -e -n " 33[47m "
else
echo -e -n " 33[40m "
fi
done
echo -e -n " 33[40m" #### set back background colour to black
echo "" #### print the new line ###
done
它工作正常。我立即在它的开头添加了一个 shibang,让它看起来像
#!/bin/sh
for (( i = 1; i <= 9; i++ )) ### Outer for loop ###
do
for (( j = 1 ; j <= 9; j++ )) ### Inner for loop ###
do
tot=`expr $i + $j`
tmp=`expr $tot % 2`
if [ $tmp -eq 0 ]; then
echo -e -n " 33[47m "
else
echo -e -n " 33[40m "
fi
done
echo -e -n " 33[40m" #### set back background colour to black
echo "" #### print the new line ###
done
然而,现在,每个白色/黑色块都打印成整行。
任何人都可以帮助我理解为什么?(我在Mac Snow Leopard下运行外壳)。谢谢!威廉
岗:
只是一个更新,我发现如果我使用"#!/bin/bash",它工作正常。所以这是sh内部实施的问题?
谢谢!
也许#!/bin/bash
?
当您要指定将使用哪个程序来解释此文本文件时,请放置#!
问题是您正在使用echo
但不幸的是,即使在符合 POSIX 的系统上,此命令行为也是不可预测的。
当-n
作为参数传递echo
或者当参数中存在转义序列时,未指定回显行为。您的代码正在使用这两种不可移植的结构。此外,它还使用非便携式-e
bashism。
有关详细信息,请查看echo POSIX手册页中的"应用程序使用"一章。
您应该使用 printf
而不是 echo
。 printf
是便携式的,旨在克服echo
限制。
#!/bin/sh
for (( i = 1; i <= 9; i++ )) ### Outer for loop ###
do
for (( j = 1 ; j <= 9; j++ )) ### Inner for loop ###
do
tot=`expr $i + $j`
tmp=`expr $tot % 2`
if [ $tmp -eq 0 ]; then
printf " 33[47m "
else
printf " 33[40m "
fi
done
printf " 33[40m" #### set back background colour to black
echo "" #### print the new line ###
done
顺便说一下,这段代码可以这样简化(至少适用于 ksh 和 bash):
for (( i = 1; i <= 9; i++ )); do
for (( j = 1 ; j <= 9; j++ )); do
printf " 33[%dm " $((((i+j)%2)?40:47))
done
printf " 33[40mn"
done
echo
是一个内置的shell(尽管它也在/bin/echo
中独立可用),因此根据shell的版本,它的行为可能会有所不同。在我的系统(OS X Mountain Lion)上:
$ which sh
/bin/sh
$ /bin/sh --version
GNU bash, version 4.2.37(2)-release (i386-apple-darwin12.2.0)
Copyright (C) 2011 Free Software Foundation, Inc.
$ /bin/sh -c "echo -e -n 'e[0;34mtest'"
-e -n e[0;34mtest # incorrect
$ which bash
/opt/local/bin/bash
$ /opt/local/bin/bash --version
GNU bash, version 4.2.37(2)-release (i386-apple-darwin12.2.0)
Copyright (C) 2011 Free Software Foundation, Inc.
...
$ /opt/local/bin/bash -c "echo -e -n 'e[0;34mtest'"
test # blue and without a newline. correct
因此,在我的Mac上,/bin/sh
不支持-e
或-n
参数中的任何一个,而/opt/local/bin/bash
则支持,类似于您所看到的。
顺便说一句,您可以使用$(( ... ))
算术展开或let
进行计算:
# with arithmetic expansion:
tmp=$(( (i + j) % 2 )) # $i and $j can be used but are not necessary
# with let:
let tmp=(i+j)%2 # no spaces allowed
# or just calculate inside the if statement directly:
if (( (i + j) % 2 == 0 )); then
....