2010-06-21 133 views
3

失去了這個bash腳本串接的jar文件名到類路徑(可變CP),while循環的值是正確的,但在子shell丟失在此相關的問題Bash variable scope變量值獲取子shell

descibed
#!/bin/bash 
CP="AAA" 
func() { 
     ls -1 | while read JAR 
     do 
       if [ ! -z "$CP" ]; then 
         CP=${CP}':' 
       fi 
       CP=${CP}${JAR} 
     done 
     echo $CP # <-- prints AAA 
} 

func 

我的問題是,因爲我不知道哪個元素是最後一個元素,所以如何保存這個值。

我是否真的必須將當前值(在循環中重複)保存到文件中?

編輯:

一位同事想出了其在這裏工作得很好

ls | xargs echo|tr ' ' : 
+1

'echo * .jar | tr'':' – 2010-06-22 14:47:59

回答

6

的問題是,在管道中使用while創建一個子shell和子shell不能影響其父此命令序列。你可以通過幾種方式解決這個問題。對於你現在在做什麼,這樣就足夠了:

for JAR in *; do 
    # Your stuff 
done 

另一個要注意的是,你shouldn't rely on parsing ls

This還介紹瞭如何避免子shell。

1

您可能會發現使用查找更多功能。

例如:

當然
export CP=$(find /home/depesz/q/ -maxdepth 1 -type f -name '*.jar' -printf ':%p' | cut -b 2-) 

集的查找選項取決於你需要/想什麼。

這是一個更接近你以前有什麼:

export CP=$(find . -maxdepth 1 -type f -name '*.jar' -printf ':%f' | cut -b 2-) 
0

隱子shell是混亂的;總是使用圓括號將它們明確。要解決您的問題,只需在子shell中移動回顯。

#!/bin/bash 
CP="AAA" 
func() { 
    ls -1 | (
    while read JAR 
    do 
     if [ ! -z "$CP" ]; then 
     CP=${CP}':' 
     fi 
     CP=${CP}${JAR} 
    done 
    echo $CP 
) 
} 
func 
+0

這實際上並不是特別有用,你所做的只是在函數退出前回顯。 – 2017-11-13 16:39:11

0

這是另一種解決方案,它避免了一個子殼的產生。關鍵是要抓住迴路輸入到一個變量(在我的例子叫做「JARS」),然後這個變量重定向到使用循環< < EOF:

JARS=$(ls -1) 

while read JAR 
do 
     if [ ! -z "$CP" ]; then 
       CP=${CP}':' 
     fi 
     CP=${CP}${JAR} 
done <<EOF 
$JARS 
EOF 

echo $CP 
+1

評估'ls'的輸出總是有問題的,如果路徑包含空白等。 – 2012-05-18 00:51:41

0

這些答案似乎都不進入實際的返回正確的值,用一個非常簡單的例程迴應答案就可以了,但是說你想要腳本的輸出,這是沒用的。我沒有最好的答案,但我沒有太多時間弄清楚,所以我只是建議輸出一個你想要的臨時文件並讀取它(驚訝它並沒有提到日期):

#!/bin/bash 
CP="AAA" 
func() { 
    ls -1 | (
    while read JAR 
    do 
     if [ ! -z "$CP" ]; then 
     CP=${CP}':' 
     fi 
     CP=${CP}${JAR} 
    done 
    echo "$CP" > /tmp/cp-value-file 
) 
} 

func 
CP=$(cat /tmp/cp-value-file) 
echo $CP 

缺點:會在某些情況下需要寫入磁盤循環的每次迭代。