2014-09-10 76 views
2

在我的腳本中,我有一個未知數的變量,其中包含要轉換爲矢量的角度。我創建了變量名,使得每個'參數'的角度的形式爲: {parameter} _angle_ {lat/perp} 因此,每個參數都有一個'lat'和'perp'角度變量。 所以我想要做的是找到所有包含'_angle_lat'的變量,對這些變量的值做一些計算並創建一個包含'參數'名稱的新變量。 例如:Bash:通過名稱中包含模式的變量循環

export M0_angle_lat=4 
export M1_angle_lat=70 
export M1_angle_perp=8 
export M0_angle_perp=90 

# Now I want to use these values to calculate vectors 
for varname in *_angle_lat 
do 
    # at first iteration it will get for example "varname=M0_angle_lat" in which case 
    # I want it to do: 
    M0_X=$(($M0_angle_lat * $M0_angle_perp)) 
    # The second iteration in case would then give "varname=M1_angle_lat" in which case 
    # I want it to do: 
    M1_X=$(($M1_angle_lat * $M1_angle_perp)) 
done 

我希望這是清楚我的目標是在這裏。謝謝您的幫助!

+2

'bash'確實不是這種類型的編程語言。它確實有數組,但它們不適合構建更復雜的數據結構,並且嘗試使用動態生成的變量名編寫代碼的情況最容易出錯。 (雖然'bash' 4.3引入了一個使它更簡單的特性。) – chepner 2014-09-10 12:32:19

+0

我使用'bash'的原因是因爲它是一個小型腳本,必須在集羣上調用,所有周圍的代碼和腳本也都在bash中。 – Bjorn 2014-09-10 12:37:16

+0

如果您可以通過前綴重寫您的變量以匹配,那麼您可以使用'$ {!prefix *}'和'$ {!prefix @}'擴展來獲取以'prefix'開頭的變量名稱。 – 2014-09-10 13:49:53

回答

6

你可以做的是使用env來獲取所有變量的列表,然後遍歷它們:

while IFS='=' read -r name value ; do 
    if [[ $name == *'_angle_lat'* ]]; then 
    echo "$name" ${!name} 
    prefix=${name%%_*} # delete longest match from back (everything after first _) 
    angle_lat="${prefix}_angle_lat" 
    angle_perp="${prefix}_angle_perp" 
    result="${prefix}_X" 
    declare "${result}=$((${!angle_lat} * ${!angle_perp}))"  
    fi 
done < <(env) 
+0

這似乎是一個巨大的進步。但在這種情況下,我有'$ var'是整個字符串:'M0_angle_lat = 4'。我如何從這裏提取'參數'(在這種情況下是'M0')? 如何使用它來創建變量'M0_X = $(($ M0_angle_lat * $ M0_angle_perp))'? – Bjorn 2014-09-10 12:41:55

+0

我看到這段代碼試圖做什麼,但它似乎並沒有工作。我剛剛檢查了羣集上運行的bash的版本,結果發現它是舊的: 'GNU bash,版本3.2.25(1) - 發佈(x86_64-redhat-linux-gnu) 版權所有(C)2005自由軟件基金會,' – Bjorn 2014-09-10 13:28:33

+0

事實證明,我以前是沒有問題的bash,但純粹的代碼中的一些小錯誤,現在已經修復! – Bjorn 2014-09-11 10:02:24

1

此代碼需要bash 4.3,使用由declare -n創建命名引用。

這也需要你稍微重新命名你的變量。

angle_lat_M0=4 
angle_lat_M1=70 
angle_perp_M1=8 
angle_perp_M0=90 

# Now I want to use these values to calculate vectors 
for varname in ${!angle_lat*} 
do 
    # Ref to angle_lat_* 
    declare -n lat=$varname 
    # Ref to angle_perp_* 
    declare -n perp=${varname/_lat_/_perp_} 
    # Ref to X_* 
    declare -n x=${varname/angle_lat_/X_} 

    x=$((lat * perp)) 
done 

echo $X_M0 
echo $X_M1 

在4.3之前,你需要一些額外的技巧來工作varname。 (事實上​​,它不是那麼糟糕,因爲我認爲這將是。)

angle_lat_M0=4 
angle_lat_M1=70 
angle_perp_M1=8 
angle_perp_M0=90 

# Now I want to use these values to calculate vectors 
for varname in ${!angle_lat*} 
do 
    tag=${varname#angle_lat_} # M0, M1, etc 
    lat=${!varname} 
    perp_name=angle_perp_$tag 
    perp=${!perp_name} 
    x=$((lat * perp)) 

    declare "X_$tag=$x" 
done 

echo $X_M0 
echo $X_M1 

就更簡單了,它應該爲bash所有版本(可能不包括 一些很老的版本,但是3.2至少支持) 。這很簡單,主要是因爲 它放棄嘗試迭代一組相似的變量名稱。

lats=($M0_angle_lat $M1_angle_lat) 
perps=($M0_angle_perp $M1_angle_lat) 
declare -a x 

for i in "${!lats[@]}"; do 
    x+=(${lats[i]} * ${perps[i]}) 
done 

M0_X=${x[0]} 
M1_X=${x[1]} 
# or 
for i in "${!x[@]}"; do 
    declare "M${i}_X"=${x[i]} 
done