將 bash 數組複製到名稱由另一個變數保存的變數
有很多類似的問題,但我不明白任何答案作為以下問題的解決方案:
我想創建一個包含兩個參數的 bash 函式,第一個是變數名,第二個是搜尋字元串(用於文件搜尋)。
結果,我希望變數名包含找到的文件的數組。
我有一個包含以下文件的目錄:
- 一個.jpg
- b.tif
- c.jpg
函式定義為:
search-files--fill-array() { local variable_name="${1}" declare -a eval ${variable_name} local search_string="${2}" echo "${search_string}" local nullglob_setting=$(shopt -p nullglob) shopt -s nullglob found_files=(${search_string}) eval "${nullglob_setting}" eval ${variable_name}=(${found_files[@]}) }
但最後一行導致語法錯誤。它應該將數組分配給作為函式第一個參數呈現的變數,因此呼叫該函式:
search-files--fill-array my_variable_a "*.jpg"
所以想要的結果應該是
echo "${my_variable_a[@]}"
將兩個文件“a.jpg”和“c.jpg”顯示為一個數組,即
echo "${#my_variable_a[@]}"
應產生“2”。
如果它不必是一個數組,解決方案是使用以下最後一行:
eval ${variable_name}=\${found_files}
在沒有任何成功的情況下,我還嘗試使用 while 循環從舊數組中形成新數組,但這也不起作用。
eval ${variable_name}="\${found_files[@]}"
生成
my_variable_a
包含字元串但不包含數組的內容。背景
也許我的方法是完全錯誤的。
為了清楚起見:我想用一個數組填充一些變數,每個變數都包含通過 globbing 找到的文件的文件名(對於不同的搜尋“字元串”總是以相同的方式)。我只希望文件,不考慮子目錄,我必須確定,結果總是可靠地排序。)
我想避免冗餘程式碼。
該
shopt
部分是必要的,以確保,如果目前目錄中不存在文件,則數組填充零條目,而沒有 nullglob,則將有一個具有搜尋“字元串”內容的條目。解決方案
正如比利叔叔建議的那樣,我可以
declare -n var
在這裡使用。工作功能:
search-files--fill-array() { declare -n function=$1 local shopt_setting=$BASHOPTS shopt -s nullglob function=($2) [[ :$shopt_setting: = *:nullglob:* ]] || shopt -u nullglob }
他提出的重置
nullglob
導致該功能不再包含的處理eval
。您可以閱讀例如這個 stackexchange 文章來了解,為什麼避免eval
值得考慮。
使用變數引用:
search-files--fill-array() { typeset -n a=$1 local s=$BASHOPTS shopt -s nullglob a=($2) [[ :$s: = *:nullglob:* ]] || shopt -u nullglob } prompt> touch foo.txt bar.txt prompt> search-files--fill-array foo '*.txt' prompt> typeset -p foo declare -a foo=([0]="bar.txt" [1]="foo.txt")
help declare
了解更多詳情(declare
是 的同義詞typeset
)。
declare -a eval ${variable_name}
這將聲明函式本地的兩個數組,一個命名
eval
,另一個命名為${variable_name}
. 無論你為它們分配什麼,它都會在函式返回後失去。用於declare -g
使它們全域化。
eval ${variable_name}=(${found_files[@]})
=> 語法錯誤與
echo foo=(bar)
=> 語法錯誤相同。(
是一個元字元,它不能在任何地方使用,但只能在命令的開頭(例如 after;
、&&
等)或作為分配給數組時使用的特殊語法的一部分。