2011-08-05 34 views
11

我試圖讓像這樣Linux shell中追加的可變參數命令

./jsdoc.sh file.js another.js maybe-a-third.js 

我被陷在給定的參數生成JSDoc bash腳本如何傳遞的參數未知量到下一個殼命令。

(也,不知道如何檢查如果param存在,只是如果沒有exitst if [ -z ... ]

此代碼的工作長達兩個參數,但顯然不是正確的方式去了解它...

#!/bin/bash 

# would like to know how to do positive check 
if [ -z "$1" ] 
then echo no param 
else 
     d=$PWD 
     cd ~/projects/jsdoc-toolkit/ 

     # this bit is obviously not the right approach 
     if [ -z "$2" ] 
     then java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $d/$1 
     else java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $d/$1 $d/$2 
     fi 

     cp -R out/jsdoc $d 
fi 

任何其他指示我怎麼能實現這一點,將不勝感激。

編輯:根據@ skjaidev的答案更新腳本 - 快樂的日子;)

#!/bin/bash 

d=$PWD 

for i in $*; do 
    params=" $params $d/$i" 
done 

if [ -n "$1" ]; then 
     cd ~/projects/jsdoc-toolkit/ 
     java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $params 
     cp -R out/jsdoc $d 
fi 
+1

爲了安全,使用'「$ @」'而不是'$ *'。我也使用'if(($#> 0))' - 「$#」是參數的數量。 –

回答

11

$ *擁有所有的參數。你可以在它們之間迭代

for i in $*; 
do 
    params=" $params $d/$i" 
done 
your_cmd $params 
+12

在這種情況下,請始終使用'「$ @」'而不是'$ *' - 前者將保留包含空白的參數,後者將受制於shell分詞。 –

+0

+1給那個Glenn。 – jman

+1

即使'「$ @」'將在其擴展中保留空格,隨後的'$ i'擴展將撤消該效果,並且當最後一行中擴展'$ params'時,帶有嵌入空格的文件名仍然會導致多個爭論的地方。一個Bash特定的解決方案是使用@glennjackman –

3

-n-z倒數,以及"[email protected]"是傳遞給子命令的所有參數的正規途徑。這和更多可以通過man bash找到。

+0

這很好 - 幾乎解決了。最後一件事是我怎樣在每個參數上加上'$ d /'來模擬'$ d/$ 1 $ d/$ 2',但是使用'$ @'來模擬? –

12

要處理包含空格的參數,請使用"[email protected]"進行迭代,並將其存儲以供以後在數組中使用。

#!/bin/bash 
if (($# == 0)); then 
    echo "usage: $0 file ..." 
    exit 
fi 
dir=$(pwd) 
declare -a params 
for file in "[email protected]"; do params+=("$dir/$file"); done 
cd ~/projects/jsdoc-toolkit/ 
java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ "${params[@]}" 
cp -R out/jsdoc "$dir" 
0

特定擊的功能(在此情況下陣列)可以通過小心使用IFS變量和特殊[email protected]參數來避免。

#!/bin/sh 

dir=$(pwd) 

NEW_ARGV="" 
# carefully modify original arguments individually and separate them with newlines 
# in a new variable (in case they contain spaces) 
NEW_ARGV="" 
for var in "${@}" 
do 
    NEW_ARGV="${NEW_ARGV} 
${dir}/${var}" 
done 

SV_IFS=${IFS} 
# temporarily set IFS to a newline as per NEW_ARGV setup 
IFS=" 
" 
# reset [email protected] with the modified newline-separated arguments 
set -- ${NEW_ARGV} 
IFS=${SV_IFS} 

# for testing, demonstrate each param is preserved 
c=0 
for i in "${@}" 
do 
    c=`expr ${c} + 1` 
    echo "args-via-var #${c}: \"${i}\"" 
done 

cd ~/projects/jsdoc-toolkit/ 
java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ "${@}" 
cp -R out/jsdoc "${dir}" 

這是沒有必要重置[email protected],但這樣做避免了在多個地方IFS搞亂。在沒有經過[email protected]的情況下,必須設置IFS到處擴大$NEW_ARGV

那些注意細節的人會注意到,當它們包含換行符時,這個方法不保留參數。可以使用任何控制字符代替換行符,當然除了NUL,並且也許ASCII FS(文件分隔符,又名ctrl-\)在有效文件名中都是有意義的並且不太可能發生。