0

シェルの習熟度を向上させるために、Linux シェル プログラミング ガイドに従っています。今日、ネストされた 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

そして、それは正しく動作します。早速、先頭にシバンをつけてこんな感じにしました

#!/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 でシェルを実行しています)。ありがとう!ウィリアム


ギャング:

ただの更新ですが、「#!/bin/bash」を使用すると正常に動作することがわかりました。それはshの内部実装の問題ですか?

ありがとう!

4

3 に答える 3

1

#!/bin/bash多分?

この#!テキストファイルを解釈するために使用するプログラムを指定したい場合に入力します

于 2012-12-02T14:48:04.807 に答える
0

問題は使用していることですがecho、このコマンドの動作は、POSIX準拠のシステムであっても、残念ながら予測できません。

-nパラメータとして渡された場合echo、または引数にエスケープシーケンスが存在する場合、エコーの動作は指定されていません。あなたのコードは、これらの移植性のない構造の両方を使用しています。-eまた、持ち運びに便利なバシズムも使用しています。

詳細については、echoPOSIXのマニュアルページの「アプリケーションの使用法」の章を参照してください。

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はシェルに組み込まれているため (ただし、 ではスタンドアロンでも使用できます/bin/echo)、シェルのバージョンによって動作が異なる場合があります。私のシステム (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
....
于 2012-12-02T23:24:48.980 に答える