【问题标题】:Pass multi-word arguments to a bash function将多字参数传递给 bash 函数
【发布时间】:2012-04-21 04:32:30
【问题描述】:

在 bash 脚本函数中,我需要使用脚本的命令行参数以及另一个参数列表。所以我试图将两个参数列表传递给一个函数,问题是多字参数被拆分。

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

    echo .

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

PARAMS="$@"
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 "$@"; do
        echo "$ITEM"
    done
}

params x y 'z t'

调用脚本给了我

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

...这就是我需要的(除了第一个列表被颠倒了,但我猜这是可以容忍的)

【问题讨论】:

    标签: bash parameters word split


    【解决方案1】:
    function params()
    {
       arg=("$@")
    
       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 $# "$@" "${items[@]}"
    

    假设您使用 args a b 'c d' 调用脚本,则输出为:

    a
    b
    c d
    .
    x
    y
    z t
    

    【讨论】:

    • 我明白了......所以你将项目单独传递给函数。在我看来,bash 在尊重引号的同时将字符串拆分为项目的唯一地方是在解释命令行时。
    • 将数组元素作为"${items[@]}"(双引号)传递的性质具有将每个元素作为"${items[0]}" "${items[1]}" "${items[2]} ...等发送的效果......如果你将它作为${items[@]}传递,你会得到使用包含空格的元素进行分词。
    【解决方案2】:

    Peter.O 上面的回答很好用,这是一个附录,带有一个例子。

    我需要一个可以接受多字参数的函数或脚本,然后将其用于搜索正在运行的进程列表并杀死与其中一个参数匹配的进程。下面的脚本就是这样做的。函数kill_processes_that_match_arguments 只需要一个for 循环,因为我只需要遍历该函数的所有参数集。经测试可以工作。

    #!/bin/bash
    
    function kill_processes_that_match_arguments()
    {
        arg=("$@")
        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[@]}"
    

    【讨论】:

      猜你喜欢
      • 2021-10-05
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多