0

我正在遵循 linux shell 编程指南来提高我对 shell 的熟练程度。今天,我到达了嵌套 for 循环的部分。

以下脚本在终端上打印棋盘。

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 "\033[47m "
        else
            echo -e -n "\033[40m "
        fi
  done
 echo -e -n "\033[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 "\033[47m "
        else
            echo -e -n "\033[40m "
        fi
  done
 echo -e -n "\033[40m" #### set back background colour to black
 echo "" #### print the new line ###
done

然而,现在,每个白色/黑色块打印一整行。

任何人都可以帮助我理解为什么?(我在 Mac Snow Leopard 下运行 shell)。谢谢!威廉


帮派:

只是一个更新,我发现如果我使用“#!/bin/bash”,它工作正常。所以是sh内部实现的问题?

谢谢!

4

3 回答 3

1

#!/bin/bash也许?

当您#!想指定将使用哪个程序来解释此文本文件时

于 2012-12-02T14:48:04.807 回答
0

问题是您正在使用echo,但不幸的是,即使在符合 POSIX 的系统上,此命令行为也是不可预测的。

-n作为参数传递echo或当参数中存在转义序列时,回显行为未指定。您的代码正在使用这两种不可移植的结构。此外,它还使用了不可移植的-ebashism。

有关详细信息,请查看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 "\033[47m "
        else
            printf "\033[40m "
        fi
  done
 printf "\033[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 "\033[%dm " $((((i+j)%2)?40:47))
  done
  printf "\033[40m\n"
done
于 2012-12-02T16:22:00.023 回答
-1

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上,不支持-eor-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
....
于 2012-12-02T23:24:48.980 回答