bash 构建包含空格的参数列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/411495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:36:38  来源:igfitidea点击:

build argument lists containing whitespace

bashargumentswhitespace

提问by tarsius

In bash one can escape arguments that contain whitespace.

在 bash 中,可以转义包含空格的参数。

foo "a string"

This also works for arguments to a command or function:

这也适用于命令或函数的参数:

bar() {
    foo "$@"
}

bar "a string"

So far so good, but what if I want to manipulate the arguments before calling foo?

到目前为止一切顺利,但是如果我想在调用之前操作参数foo怎么办?

This does not work:

这不起作用:

bar() {
    for arg in "$@"
    do
        args="$args \"prefix $arg\""
    done

    # Everything looks good ...
    echo $args

    # ... but it isn't.
    foo $args

    # foo "$args" would just be silly
}

bar a b c

So how do you build argument lists when the arguments contain whitespace?

那么当参数包含空格时如何构建参数列表呢?

回答by tarsius

There are (at least) two ways to do this:

有(至少)两种方法可以做到这一点:

  1. Use an array and expand it using "${array[@]}":

    bar() {
        local i=0 args=()
        for arg in "$@"
        do
            args[$i]="prefix $arg"
            ((++i))
        done
    
        foo "${args[@]}"
    }
    

    So, what have we learned? "${array[@]}"is to ${array[*]}what "$@"is to $*.

  2. Or if you do not want to use arrays you need to use eval:

    bar() {
        local args=()
        for arg in "$@"
        do
            args="$args \"prefix $arg\""
        done
    
        eval foo $args
    }
    
  1. 使用数组并使用"${array[@]}"以下方法展开它:

    bar() {
        local i=0 args=()
        for arg in "$@"
        do
            args[$i]="prefix $arg"
            ((++i))
        done
    
        foo "${args[@]}"
    }
    

    所以我们学了什么?"${array[@]}"${array[*]}什么"$@"是什么$*

  2. 或者,如果您不想使用数组,则需要使用eval

    bar() {
        local args=()
        for arg in "$@"
        do
            args="$args \"prefix $arg\""
        done
    
        eval foo $args
    }
    

回答by Jaen

Here is a shorter version which does not require the use of a numeric index:

这是一个不需要使用数字索引的较短版本:

(example: building arguments to a findcommand)

(例如:为find命令构建参数)

dir=
shift
for f in "$@" ; do
    args+=(-iname "*$f*")
done
find "$dir" "${args[@]}"

回答by JesperE

Use arrays(one of the hidden featuresin Bash).

使用数组(Bash中的隐藏功能之一)。

回答by jpalecek

You can use the arrays just as you suggest, with a small detail changed. The line calling foo should read

您可以按照您的建议使用数组,只是更改了一个小细节。调用 foo 的行应为

 foo "${args[@]}"

回答by TJ L

I had a problem with this too as well. I was writing a bash script to backup the important files on my windows computer (cygwin). I tried the array approach too, and still had some issues. Not sure exactly how I fixed it, but here's the parts of my code that are important in case it will help you.

我也有这个问题。我正在编写一个 bash 脚本来备份我的 Windows 计算机(cygwin)上的重要文件。我也尝试了数组方法,但仍然存在一些问题。不确定我是如何修复它的,但这是我的代码中很重要的部分,以防它对您有所帮助。

WORK="d:\Work Documents\*"
#   prompt and 7zip each file
for x in $SVN $WEB1 $WEB2 "$WORK" $GRAPHICS $W_SQL
do
    echo "Add $x to archive? (y/n)"
    read DO
    if [ "$DO" == "y" ]; then
        echo "compressing $x"
        7zip a $W_OUTPUT "$x"
    fi
    echo ""
done