2012-08-17 47 views
10

我寫了一個樣本KornShell函數來分割一個String,將它放入一個數組中,然後打印出這些值。 的代碼如下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

疑難雜症!!!! 該腳本正在工作,沒有問題。做了一個以錯誤的方式調用函數的小錯誤。 但是仍然想了解KSH的變量範圍 – Vivek 2012-08-17 06:47:32

回答

16

變量的默認範圍是整個腳本。

但是,當你聲明函數內部變量,該變量成爲局部聲明它的功能。 Ksh有dynamic scoping,所以變量也可以在聲明該變量的函數調用的函數中訪問。這在section on functions in the manual中有詳細記錄。注意,在AT &Ťksh的(相對於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。此外,您應該關閉globbing,否則如果字符串包含shell globbing字符?*\[,並且其中一個單詞碰巧與您的系統上的一個或多個文件相匹配,則它將被展開。 set -A $string其中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 2012-08-17 11:43:54

+0

@cdarke你是對的,謝謝。你碰巧知道ksh88的情況?我無法重現提問者在ksh93中描述的行爲。 – Gilles 2012-08-17 11:54:11

+0

在ksh88(和bash)中,對兩種函數聲明風格的作用域都是一樣的。在ksh93中,POSIX函數語法具有POSIx功能,沒有其他功能,因此函數跟蹤也受到影響。 – cdarke 2012-08-17 14:41:07

2

變量通常是全局的,它們是從定義的時候開始定義的。

typeset命令可以使他們本地他們在定義,或者使它們自動導出功能(即使他們更新。)

閱讀了「排版」和「整數」在該手冊或Korn的書。

+0

感謝Abe的提示。我將在手冊頁上進行讀取 – Vivek 2012-08-17 09:04:03