2011-05-01 53 views
7

在循環這樣的變量時出現問題。我準備了兩個例子來展示這個問題。

EX1:

#!/bin/bash 
DIRS="[email protected]" 

for DIR in $DIRS; do 
    echo "$DIR" 
done 

EX2:

#!/bin/bash 
for DIR in "[email protected]"; do 
    echo "$DIR" 
done 

第二個例子的工作原理如預期(和所需的)。快速測試如下:

$ ex1 "a b" "c" 
a 
b 
c 
$ ex2 "a b" "c" 
a b 
c 

究其原因,我爲什麼要使用第一種方法是因爲我希望能夠到多個目錄傳遞給程序或沒有使用當前目錄。像這樣:

[ $# -eq 0 ] && DIRS=`pwd` || DIRS="[email protected]" 

那麼,我如何得到例1是空間安全的?

回答

10

使用數組而不是簡單變量。

declare -a DIRS 

DIRS=("[email protected]") 

for d in "${DIRS[@]}" 
do echo "$d" 
done 

這產生的結果:

$ bash xx.sh a "b c" "d e f g" h z 
a 
b c 
d e f g 
h 
z 
$ 
+0

Aaah,我嘗試了很多,我非常接近。我只是忘了$ {DIRS [@]}的引號。謝謝 – Frank 2011-05-01 23:01:42

+0

@Frank:數組符號有點繁瑣 - 每次使用它時都必須返回參考手冊。我越來越好,但有多年Bourne shell經驗可以覆蓋。 – 2011-05-01 23:07:35

0

一種方法是,當你使用參數與別的參數內再次更換空間,然後代替空格:

dirs="${@/ /###}" 
for dir in $dirs; do 
    echo "${dir/###/ }" 
done 

這依賴於你能拿出一串字符你可以確信自己永遠不會出現在真實的文件名中。

對於你有,你希望能夠提供目錄的顯式列表或默認爲當前目錄之間進行選擇的具體情況,更好的解決辦法可能是使用的函數:

do_something() { 
    for dir in "[email protected]"; do 
     echo "$dir" 
    done 
} 

if [ $# -eq 0 ]; then 
    do_something . 
else 
    do_something "[email protected]" 
fi 

或可能:

do_something() { 
    echo "$1" 
} 

if [ $# -eq 0 ]; then 
    do_something . 
else 
    for dir in "[email protected]"; do 
     do_something "$dir" 
    done 
fi 
4

爲什麼不使用默認的擴展功能?

for DIR in "${@:-$(pwd)}"; do 
    echo $DIR 
done