2012-08-17 20 views
10

文字列を分割して配列に格納し、値を出力するサンプルのKornShell関数を記述しました。 コードはKSHの変数の範囲

#!/usr/bin/ksh 

splitString() { 

    string="[email protected];[email protected];[email protected]" 

    oIFS="$IFS"; 
    IFS=';' 
    set -A str $string 
    IFS="$oIFS" 
} 

splitString 
echo "strings count = ${#str[@]}" 
echo "first : ${str[0]}"; 
echo "second: ${str[1]}"; 
echo "third : ${str[2]}"; 

今すぐechoは、配列の値をプリントアウトしていない以下のようなので、私はそれが定義された配列の範囲とは何かを持っていると仮定します。

私はシェルスクリプトの初心者ですが、上記の例で変数の範囲を理解するのに誰も助けてくれますか?

+0

Gotcha !!!! スクリプトは動作していますが、問題はありません。関数を間違った方法で呼び出すという小さな誤りがあった。 しかし、まだKSHの変数の範囲を理解したいと思うでしょう – Vivek

答えて

16

変数のデフォルトスコープはスクリプト全体です。

しかし、関数内で変数を宣言すると、その変数は宣言している関数に対してローカルになります。 Kshはdynamic scopingなので、変数を宣言する関数によって呼び出される関数で変数にアクセスすることもできます。これはsection on functions in the manualに簡潔に記載されています。 AT & Tksh(pdkshと派生語、およびbashとzshの類似の機能とは対照的)では、これはfunctionキーワードで定義された関数にのみ適用され、従来のf() { … }構文で定義された関数には適用されません。 AT & T ksh93では、従来の構文で定義された関数で宣言されたすべての変数はグローバルです。

変数を宣言する主な方法は、typesetbuiltinです。それは常にローカル変数を作成します(AT & T ksh、functionで宣言された関数のみ)。 typesetで宣言していない変数に代入すると、グローバルになります。

kshのドキュメントでは、set -Aがローカル変数またはグローバル変数を作成するかどうかは指定されておらず、異なるバージョンでもどちらかが作成されます。 ksh 93u、pdkshまたはmkshでは、変数はグローバルであり、スクリプトは値を出力します。スコープがローカルのksh88または古いバージョンのkshがあるようです。関数の外にstrを初期化するとグローバル変数が作成されると思いますが、わかりません。

IFSの値を上書きするには、ローカル変数を使用する必要があります。別の変数への保存は不器用であるだけでなく、設定されていなければIFSを適切に復元しないため脆弱です。さらに、文字列にシェルグロブ文字?*\[が含まれていて、その単語の1つがシステム上の1つ以上のファイルと一致すると、globbingがオフになるはずです。 set -A $stringa;*の場合、現在のディレクトリにファイル名のリストを含むstrになります。

set -A str 
function splitString { 
    typeset IFS=';' globbing=1 
    case $- in *f*) globbing=;; esac 
    set -f 
    set -A str $string 
    if [ -n "$globbing" ]; then set +f; fi 
} 
splitString "$string" 
+0

あなたはPOSIX関数の構文を使用しています。 ksh93では、 'function splitSpring {...}'を使うと 'typeset'でスコープがうまくいきます。そうでなければ、スコープの目的でタイプセットは無視されます。 – cdarke

+0

@cdarkeあなたは正しいです、ありがとう。 ksh88の状況を知っていますか?私は、askerがksh93で説明した動作を再現することはできません。 – Gilles

+0

ksh88(およびbash)スコープでは、両方のスタイルの関数宣言で同じ動作が行われます。 ksh93では、POSIX関数の構文にはPOSIxの機能があり、それ以外の機能はありません。したがって、関数のトレースも影響を受けます。 – cdarke

2

通常、変数は定義されてから定義されたシェルにとってグローバルです。

typesetコマンドは、(それらが更新されている場合でも。)彼らはで定義されている関数にそれらをローカルにすることができ、あるいはそれらを自動的にエクスポートするために

に「タイプセット」と「整数」まで読みますマンページ、またはKornの本。

+0

チップのために阿部に感謝します。私は、マンページでの読み上げを行います – Vivek