web-dev-qa-db-ja.com

bashスクリプトのforループ

次のbashのforループはエラーになります-

line 42: 1
2
3
4
5 + 1: syntax error in expression (error token is "2
3
4
5 + 1")

42行目はステートメント-num1 = $ [$ i1 + 1]

for i1 in `seq 1 5`
    do
    num1=$[$i1 + 1]
        for k1 in `seq $num1 5`
        do
        ky1="${team_two[i1]}_${team_two[k1]}"
        pair_score[$ky1]=$[${pair_score[$ky1]}+1]
        done
    done

コードの何が問題になっていますか?

[〜#〜]編集[〜#〜]

デバッグ時に次の出力が表示されます

++ seq 1 5
+ for i1 in '`seq 1 5`'
/home/ashwin/bin/calculate_power: line 43: 1
2
3
4
5 + 1: syntax error in expression (error token is "2
3
4
5 + 1")

繰り返しますが、43行目と同じステートメントです-num1 = $ [$ i + 1]

2
Ashwin

${team_two[*]}${team_two[k1]}配列に問題があるか、特殊変数$IFSの区切り文字をいじったようです。外側のforループに入る前に、set -xを追加することで、Bashデバッグをオンにできます。その後、set +xを使用して無効にし、さらに洞察を得ます。

set -x
... for loop block ...
set +x

この方法でBashを介してコードを実行すると、次の出力が得られます。

$ bash -x for.bash 
++ seq 1 5
+ for i1 in '`seq 1 5`'
+ num1=2
++ seq 2 5
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=1
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=2
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=3
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=4
+ for i1 in '`seq 1 5`'
+ num1=3
++ seq 3 5
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=5
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=6
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=7
+ for i1 in '`seq 1 5`'
+ num1=4
++ seq 4 5
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=8
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=9
+ for i1 in '`seq 1 5`'
+ num1=5
++ seq 5 5
+ for k1 in '`seq $num1 5`'
+ ky1=_
+ pair_score[$ky1]=10
+ for i1 in '`seq 1 5`'
+ num1=6
++ seq 6 5

編集#1

さらに更新した後、$IFSをリセットしたように見えます。通常、リセットする前に$IFSを2次変数に保存し、後で元の値に戻す必要があります。

IFSOLD=$IFS
IFS=,

... do IFS , stuff here ...

IFS=$IFSOLD

IFS

これらの例を試してみると、スクリプト内で使用したときに$IFSが及ぼす影響にさらに光を当てるのに役立つ可能性があります。

次の変数があるとします。

$ var="1,2,3,4,5"

それを解析して、最初の変数$c1を出力しましょう。

$ IFS=',' read -r c1 c2 c3 c4 c5 <<< "$var"
$ echo "$c1"
1

ただし、$IFSをスペースに変更した場合。

$ IFS=' ' read -r c1 c2 c3 c4 c5 <<< "$var"
$ echo "$c1"
1,2,3,4,5

したがって、2番目の例では、$IFSを介してreadコマンドを、コンマではなくスペースで分割するように構成しました。

4
slm

そのコードには(基本的に)何も問題はありません。問題は、「IFS」を別の場所にリセットしたことです。おそらくです(したがって、seqの出力は単一のトークンとして扱われます)。

_$[]_を見てから長い時間、それは 廃止 (そして文書化されていない)です。 $(( ))を使用します。

seqの代わりにfor (( ))を使用し、1を追加する代わりに_let var++_を使用すると、次のようになります。

_for (( i1=1 ; i1<=5; i1++))
    do
        for ((k1=i1+1; k1<=5; k1++))
            do
                ky1="${team_two[i1]}_${team_two[k1]}"
                let pair_score[$ky1]++
            done
    done    
_

連想配列で最近のbashを使用しているので、他のNice機能も使用することもできます:-)

3
mr.spuratic