de[v|b]log

ShellScript, Coffee, iOS/OSX Dev
Origin: Himajinworks.
About.

実はこれまで(P)オプションを知らなかったのでそれと、前日の記事でも扱ったprivateに関してももう少し試します。

気づいたこと

privateで配列による初期化はできない

過去にlocalであったみたいに、宣言と同時の初期化はできないっぽい。

1
2
3
4
5
# できる
private str='string'

# できない
private -a arr=(a b c d e)

やってみたらこれができなかった。(localにかんしては、今はできる)

1
2
local -a array_1=(a b c d e)
local -a array_2=(1 2 3 4 5)

これがやりたかったので、以下で代用した。

1
2
3
private -a array_1 array_2
array_1=(a b c d e)
array_2=(1 2 3 4 5)

ループ内でprivateは使えないっぽい

以下の様なコードを書いた。

1
2
3
4
5
private idx
for idx ({1..10}); do
    private name="User ${idx}"
    # ...
; done

このとき、can't change scope of existing param: nameというエラーとともに対象のシェルスクリプト(が走っているサブシェル)がSegmentation Faultで落ちるという現象に遭遇した。

つまりもしprivateで上記のnameのような変数を使いたい場合

1
2
3
4
5
private idx name
for idx ({1..10}); do
    name="User ${idx}"
    # ...
; done

こうしないといけなかった。(リファレンス未参照)

(P)による変数へのアクセス

ここで(P)により受け取った変数の中身を変数名として扱う(P)をもう少し試す。 ここれはarray_1array_2として定義した配列に対してアクセスする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#! /usr/bin/env zsh

function todo()
{
    private -a array_1 array_2
    array_1=(a b c d e)
    array_2=(1 2 3 4 5)

    private idx name
    for idx (1 2); do
        name="array_${idx}"
        for arr_idx ({1..${#${(P)name}}}); do
            echo ${${(P)name}[${arr_idx}]}
        ; done
    ; done
}

todo
1
2
3
4
5
6
7
8
9
10
a
b
c
d
e
1
2
3
4
5

が出力され、求める結果となった。

Bus errorに出会う

以下のようなコードがある。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#! /usr/bin/env zsh

function todo()
{
    private dim=${1}
    private -a vector_names
    private vname d i init_val
    private -a v

    # Initialize
    for d ({1..${dim}}); do
        eval "private -a vec_${d}"
        vname="vec_${d}"
        vector_names=(${vector_names} ${vname})

        for i ({1..${dim}}); do
            init_val=$(((${d} - 1) * ${dim} + ${i}))
            eval "${vname}=(${(P)vname} ${init_val})"
        ; done
    ; done

    # Output
    for vname (${vector_names}); do
        v=(${(P)vname})
        for i (${v}); do
            echo -n "${i} "
        ; done
        echo ''
    ; done
}

todo 3

これはtodo nとして与えたnの値に応じてn x n行列を作成し、表示するものである。(わざとループを使っている) このとき、privateを用いていると、

1
2
1 2 3
[1]    53292 bus error  ./task.sh

bus errorに出会う。これは、privatelocalに変えるとしっかりと動くことを確認しており、ここもまたprivateを使う際の問題になりそうであると思った。

そういえば

  • Homebrewで早速zsh 5.2が降ってきました