2013-10-05 49 views
0

我在bash和ksh中都有間接引發的問題。下面的例子適用於ksh。它使用了一個nameref(typeset -n),但它不像我預期的那樣工作。 func_a將數組的名稱傳遞給func_b,以便它可以被修改(在這種簡單的情況下,func_b將第二個條目添加到數組中)。這顯然不起作用,因爲在func_b中定義的第二個局部變量var 與nameref var2引用的名稱(來自func_a的數組var1)具有相同的名稱。 但是,有一個本地nameref類型(與bash中使用的各種eval hacks相對)的原因之一不應該是不必處理這些動態範圍問題,其中函數(本例中爲func_b)對於某些調用者而言,按照預期的方式工作,而僅僅因爲局部定義的變量的名稱而不適用於其他人? 似乎nameref var基本上只是一個別名或宏,而不是連接兩個嚴格分隔的作用域的安全方式。我和bash有同樣的問題,我希望ksh能像C一樣實現間接引用(當然,出於安全原因,當然不像低級指針,但至少在類似的「範圍隔離」中可以這麼說)。我錯過了什麼嗎?在bash和ksh中的間接引用

func_b() 
{ 
    typeset -n var2=$1 
    typeset -i var1 

    var2[1]=b 
} 


func_a() 
{ 
typeset -a var1=(a) 
func_b var1 
echo "${var1[@]}" 
} 
+1

「看來,一個nameref VAR基本上只是一個別名或宏,而不是連接兩個嚴格區分範圍的安全方法。」但是,實際上,nameref *只是一個字符串。連接兩個嚴格分離的示波器並不是一種安全的方法。我猜你缺少的是shell腳本語言的本質。 – rici

+0

考慮編輯您的問題以包括您的樣本輸入,所需輸出和當前輸出。從您的文本描述中很難分辨出您的期望是什麼,而示例輸入和輸出將非常容易理解。祝你好運。 – shellter

回答

0

我找到了一個解決方案,以及這傢伙確實http://fvue.nl/wiki/Bash:_Passing_variables_by_reference 充滿貸款給他。我不喜歡他使用關於bash未設置的發現的方式 ,但任何人都可以用他們自己的方式使用這個屬性。因此,這裏是它的要點是:

上面的代碼會是這樣在bash

func_b() 
{ 
    local var2=$1 
    local -i var1 
#do some work to compute the value b 
#.... 
#.... 
#And in the end assign it with the indirect reference 
    eval "$var2[1]=b" 
} 


func_a() 
{ 
local -a var1=(a) 
func_b var1 
echo "${var1[@]}" 
} 

(可避免EVAL使用,但是讓我們留點) 問題是明顯func_b當地VAR1在func_b中隱藏var2在var2中引用的func_a 中的var1。因此,func_b的行爲如預期的那樣,即只有當調用者不爲 命名其數組「var1」時,調用者數組中的第二個條目 才被間接引用添加。假設在「做一些工作」部分之後,我知道我已經完成了 與本地變量var1我在func_b中使用(可能用於計算想要的 值b)。在這一點上,我可以做到這一點

func_b() 
{ 
    local var2=$1 
    local -i var1 
#do some work to compute the value b 
#.... 
#.... 
#And in the end assign it with the indirect reference 
    unset var1 
    eval "$var2[1]=b" 
} 

刪除func_a的var1「陰影」,並正確終止計算。 但bash未設置不允許。一旦我在func_b中設置了loval var1,即使 在某個點我沒有設置它,它仍然會影響func_a的var1。 上面發現的一個問題是,事實上unset實際上可以通過調用堆棧 並且取消設置func_b的var1,但是隻有當函數f的調用位於堆棧IF函數f中的func_b的調用 上時,纔會定義它自己的var1本地。 基本上,如果你這樣做

func_the_unshadower() 
{ 
    unset -v var1 
} 

func_b() 
{ 
    local var2=$1 
    local -i var1 
#do some work to compute the value b 
#.... 
#.... 
#And in the end assign it with the indirect reference 
    func_the_unshadower 
    eval "$var2[1]=b" 
} 

func_a() 
{ 
local -a var1=(a) 
func_b var1 
echo "${var1[@]}" 
} 

工程.... 顯然,這僅僅是一個玩具例子,大家可以計算出使用的未設置該屬性他們的首選 方式。一個簡單的方法是在運行時檢查通過名稱調用 的變量是否通過調用不帶參數的「local」(其中 返回本地變量列表)來影響某個本地變量。 但是,偉大的事情是,這不是在bash中的錯誤。在上面的鏈接中,有 甚至連接到bash郵件列表中的一個線程,其中主bash開發者 表示這是未設置的行爲方式,它將保持這種方式。

0

我發現,宣佈與函數的語法:

function func_a 

,它的作品。這是因爲這個ksh93語法使排版聲明的變量爲本地的,而使用原始語法應用POSIX規則並且變量是全局的。

皮特