2012-04-08 37 views
11

裏面bash腳本的功能,我需要的腳本的命令行參數來工作,還與另一個參數列表。所以我試圖將兩個參數列表傳遞給一個函數,問題是多字參數被分割。通多字的參數bash函數

function params() 
{ 
    for PARAM in $1; do 
     echo "$PARAM" 
    done 

    echo . 

    for ITEM in $2; do 
     echo "$ITEM" 
    done 
} 

PARAMS="[email protected]" 
ITEMS="x y 'z t'" 
params "$PARAMS" "$ITEMS" 

調用腳本給我

myscript.sh a b 'c d' 
a 
b 
c 
d 
. 
x 
y 
'z 
t' 

既然有兩份名單,他們必須作爲一個整體的功能被傳遞,問題是,如何遍歷的元素,同時尊重多字的項目用單引號'cd'和'z t'括起來?

,我有(見下文)的解決方法是利用BASH_ARGV的,所以我只是需要一個列表傳遞給函數。不過,我想更好地瞭解正在發生的事情以及完成上述工作所需的內容。

function params() 
{ 
    for PARAM in "${BASH_ARGV[@]}"; do 
     echo "$PARAM" 
    done 

    echo . 

    for ITEM in "[email protected]"; do 
     echo "$ITEM" 
    done 
} 

params x y 'z t' 

調用腳本給我

myscript.sh a b 'c d' 
c d 
b 
a 
. 
x 
y 
z t 

...這是我需要它(除了第一個列表是相反的,但是這將是容忍我猜)

回答

7
function params() 
{ 
    arg=("[email protected]") 

    for ((i=1;i<=$1;i++)) ;do 
     echo "${arg[i]}" 
    done 

    echo . 

    for ((;i<=$#-$1+2;i++)) ;do 
     echo "${arg[i]}" 
    done 
} 

items=(w x 'z t') 
params $# "[email protected]" "${items[@]}" 

假設您使用參數a b 'c d'調用腳本,輸出爲:

a 
b 
c d 
. 
x 
y 
z t 
+0

我明白了......所以你將項目單獨傳遞給函數。在我看來,只有在解釋命令行時,bash將字符串拆分爲多個項目時纔會考慮引號。 – haelix 2012-04-08 15:51:01

+0

將數組元素作爲''{{items [@]}「'(在雙引號中)傳遞的性質具有將每個元素作爲'」$ {items [0]}「」$ {items [1] }「」$ {items [2]} ...'等等......如果您將它作爲'$ {items [@]}傳遞',您將得到包含空格的元素的分詞。 – 2012-04-08 17:18:03

1

Peter.O的答案上面的工作很好,這是對它的一個補充,舉一個例子。

我需要一個函數或腳本,將採取多字參數,然後將用於搜索正在運行的進程列表並殺死匹配其中一個參數的列表。以下腳本執行此操作。該功能kill_processes_that_match_arguments只需要一個for循環,因爲我需要纔來遍歷集合的所有函數的自變量。測試工作。

#!/bin/bash 

function kill_processes_that_match_arguments() 
{ 
    arg=("[email protected]") 
    unset PIDS_TO_BE_KILLED 

    for ((i=0;i<$#;i++)) 
    do 
     unset MORE_PIDS_TO_KILL 
     MORE_PIDS_TO_KILL=$(ps gaux | grep "${arg[i]}" | grep -v 'grep' | awk '{ print $2 }') 
     if [[ $MORE_PIDS_TO_KILL ]]; then 
      PIDS_TO_BE_KILLED="$MORE_PIDS_TO_KILL $PIDS_TO_BE_KILLED" 
     fi 
    done 

    if [[ $PIDS_TO_BE_KILLED ]]; then 
     kill -SIGKILL $PIDS_TO_BE_KILLED 
     echo 'Killed processes:' $PIDS_TO_BE_KILLED 
    else 
     echo 'No processes were killed.' 
    fi 
} 

KILL_THESE_PROCESSES=('a.single.word.argument' 'a multi-word argument' '/some/other/argument' 'yet another') 
kill_processes_that_match_arguments "${KILL_THESE_PROCESSES[@]}"