2017-08-28 47 views
1

我正在寫for循環。但是循環取決於位置參數的內容。bash:如果分支爲兩個不同的循環

  • 如果位置參數是seq 2 1 10,環路是for i in $(seq 2 1 10)

  • 如果位置參數是純粹的數字,例如1 2 5 7 10,則環路是for i in 1 2 5 7 10

我想這一點,但沒有奏效:

test() { 
if [[ $1 == seq ]] 
then 
for i in $(seq $2 $3 $4) 
else 
for i in [email protected] 
fi 
do 
echo $i 
done 
} 

我也試過這樣:

test2() { 
if [[ $1 == seq ]] 
then 
sss="for i in $(seq $2 $3 $4)" 
else 
sss="for i in [email protected]" 
fi 
$sss 
do 
echo $i 
done 
} 

也不起作用。

所以我的問題是:

  1. 我知道我可以,如果裏面明確寫二環路。但是,如果循環內容很大,這會浪費代碼空間。有沒有更好的方法?
  2. 在我的第二次嘗試中,爲什麼$sss不會擴展爲for句子,並通過bash正確解析?
+0

'test'不是函數的最佳名稱,因爲它與shell內建'test'衝突。 – codeforester

回答

1

將數字列表保存在數組中。

test() { 
    if [[ $1 == seq ]] 
    then 
     numbers=($(seq "$2" "$3" "$4")) 
    else 
     numbers=("[email protected]") 
    fi 

    for i in "${numbers[@]}" 
    do 
     echo $i 
    done 
} 

在我的第二次嘗試,爲什麼不$sss擴展到for句子並獲得通過的bash正確解析?

變量可以被擴展成一個命令來運行,但不進入流動控制構造像for環或if語句。這些需要直接寫出來,它們不能存儲在變量中。如果嘗試,bash將嘗試運行名爲for的命令 - 也就是說,它將在/bin,/usr/bin等中查找名爲for的二進制文件。

1

使用數組作爲在John Kugelman的回答的替代方法是使用set --改變位置參數:

test() 
{ 
    if [[ $1 == seq ]]; then 
     set -- $(seq $2 $3 $4) 
    fi 
    for i; do 
     echo $i 
    done 
} 

注意for i相當於for i in "[email protected]"

John已經提到了它爲什麼不起作用 - 在控制流被解析之後發生變量插值和分裂。

+0

非常感謝你介紹'set --' – user15964