2014-11-20 66 views
2

我想讀了3個不同名稱的不同陣列類似文件的功能。因爲我不想使用不必要的代碼,我正嘗試創建可以接受數組名稱作爲參數的函數,但是我收到錯誤「未找到命令」。傳遞變量名作爲參數去在bash

hello.sh文件代碼:

#!/bin/bash 
declare -a row_1 
declare -a row_2 
declare -a row_3 


load_array() 
{ 
ROW="$2" 
let i=0 
while read line; do 
    for word in $line; do 
    $ROW[$i]=$word   
((++i)) 
    done 
done < $1 
} 

load_array $1 row_1 
load_array $2 row_2 
load_array $3 row_3 

調用從終端這個文件有:錯誤我得到的sh hello.sh 1.txt 2.txt 3.txt

列表:

hello.sh: line 13: row_1[0]=9: command not found 
hello.sh: line 13: row_1[1]=15: command not found 
hello.sh: line 13: row_1[2]=13: command not found 
hello.sh: line 13: row_2[0]=12: command not found 
hello.sh: line 13: row_2[1]=67: command not found 
hello.sh: line 13: row_2[2]=63: command not found 
hello.sh: line 13: row_3[0]=75: command not found 
hello.sh: line 13: row_3[1]=54: command not found 
hello.sh: line 13: row_3[2]=23: command not found 
+0

BashFAQ#6是話題的這個問題的許多變種:http://mywiki.wooledge.org/BashFAQ/006 – 2014-11-21 01:33:54

回答

1

在賦值語法,什麼是在等號左邊必須是變量名稱(分配給標量時),或變量名稱後面跟着方括號中的單詞(分配給數組ele MENT)。在您的代碼中,$ROW[$i]=$word與此語法不匹配(開頭處有$,因此它不可能是任務);這只是一個恰巧包含字符=的單詞。

在bash中,你可以使用內置declare分配給其名稱是一些計算結果的變量,如變量擴展。請注意,與直接分配不同,您需要在值部分周圍使用雙引號,以防止在$word上進行分詞和文件名擴展。如果您在函數中執行賦值並且希望在函數返回後保留該值,請通過選項-g

declare -g $ROW[$i]="$word" 

如果您運行的是舊版本的bash不具有declare -g,你可以使用eval代替。這將是用於在plain sh中分配給動態命名變量的方法。注意正確地引用內容:如果ROW是例如row_1,那麼作爲參數傳遞給eval的字符串必須是row_1[$i]=$word(要解析並執行的shell命令)。

eval "$ROW[\$i]=\$word" 
+0

好像這種聲明使得只有本地作業和不允許在全局中使用聲明的值。這是我得到的變量的回聲:http://i.imgur.com/SSlUNWL.png – user2816626 2014-11-20 21:59:57

+0

@ user2816626啊,對不起,我沒有注意到你需要函數外的值。添加選項'-g'(請參閱我的編輯)。 – Gilles 2014-11-20 23:08:03

+0

這是一個很好的解決方案。我以前從未見過。我會假設你必須使用'eval'或'$ {!ROW}'類型的構造。學習已經發生。 – 2014-11-20 23:26:56

0

與現代(4.3及更高版本的bash)要做到這一點語法是這樣的理想方法:

load_array() { 
    declare -n _load_array__row=$2 
    declare -a _load_array__line 
    _load_array__row=() 
    while read -r -a _load_array__line; do 
    _load_array__row+=("${_load_array__line[@]}") 
    done <"$1" 
} 

(變量名是奇減少與調用函數衝突的機會;另例如,如果要求將內容加載到名稱爲ROWline的變量中,則給出的回答將會遇到問題,因爲它們將引用局部變量而不是全局描述其目標)。


類似的機制使用bash 3.2(古代發佈蘋果發貨),避免與內環路相關的性能問題,並與水珠擴張相關的bug兼容(看看你原來的代碼確實包含*線!)如下:

load_array() { 
    local -a _load_array__array=() 
    local -a _load_array__line 
    while read -r -a _load_array__line; do 
    _load_array__array+=("${_load_array__line[@]}") 
    done <"$1" 
    eval "$2=(\"\${_load_array__array[@]}\")" 
}