无法将用双引号括起来的多字参数保留为 Bash 函数中的单个参数

无法将用双引号括起来的多字参数保留为 Bash 函数中的单个参数

我一直被 Bash 脚本中的变量扩展问题所困扰,当将一个被空格包围的多字参数传递到函数链中时,它会被拆分成多个参数。

例如:

"this entire string"

变成:

"this
entire
string"

从导致问题的代码中提取出函数的排列,下面是我能想到的重现该问题的方法:

#!/usr/bin/env bash

# The function that gets called from outside the script
wrapper_function () {
    echo "1: Parameter count: $#"
    for i in "$@"; do
        echo "wrapper_function - $i"
    done
    actual_function $@
}

# The actual low-level function that does something useful
actual_function () {
    echo "2: Parameter count: $#"
    for i in "$@"; do
        echo "actual_function - $i"
    done
}

# Setting the value of the 'problematic' argument
some_string="\"five-1 five-2\""

# Calling the function with a collated set of arguments
wrapper_function "one two three four ${some_string}"

运行这个我会得到:

1: Parameter count: 1
wrapper_function - one two three four "five-1 five-2"
2: Parameter count: 6
actual_function - one
actual_function - two
actual_function - three
actual_function - four
actual_function - "five-1
actual_function - five-2"

相反,我期望:

1: Parameter count: 1
wrapper_function - one two three four "five-1 five-2"
2: Parameter count: 5
actual_function - one
actual_function - two
actual_function - three
actual_function - four
actual_function - "five-1 five-2"

我能做些什么来解决这个问题,也许引用一些论点或者以其他方式传递它们?

我发现了一个类似问题这个可能看起来像是重复的,但我认为不是。

答案1

只需进行适当的引用

#! /bin/bash

function level3 {
    printf -- "-- Level3 ------\nGot %d arguments:\n" $#
    for arg in "$@"
    do
        printf "%s\n" "$arg"
    done
    printf -- "--------\n"
}

function level2 {
    printf -- "-- Level2 ------\nGot %d arguments:\n" $#
    for arg in "$@"
    do
        printf "%s\n" "$arg"
    done
    printf -- "--------\n"
    level3 "$@"
}

function level1 {
    printf -- "-- Level1 ------\nGot %d arguments:\n" $#
    for arg in "$@"
    do
        printf "%s\n" "$arg"
    done
    printf -- "--------\n"
    level2 "$@"
}

level1 "$@"

给出:

>>./quotes a bc "\"abc def\""
-- Level1 ------
Got 3 arguments:
a
bc
"abc def"
--------
-- Level2 ------
Got 3 arguments:
a
bc
"abc def"
--------
-- Level3 ------
Got 3 arguments:
a
bc
"abc def"
--------

答案2

好吧,经过一番尝试,我终于自己解决了这个问题,我认为这真的可以帮助遇到这种问题的人。解决方案基本上需要进行两处更改:

  1. 需要使用两个参数而不是一个参数来调用该函数wrapper_function。我会将第一组“常用”参数作为单个字符串传递,然后将“有问题”的参数作为第二组传递。
  2. 该函数actual_function需要将两个接收到的参数分别传递到链中,而不是将整个集合作为引用$@

代码现在看起来像这样:

#!/usr/bin/env bash

# The function that gets called from outside the script
wrapper_function () {
    echo "1: Parameter count: $#"
    for i in "$@"; do
        echo "wrapper_function - $i"
    done
    actual_function $1 "$2"
}

# The actual low-level function that does something useful
actual_function () {
    echo "2: Parameter count: $#"
    for i in "$@"; do
        echo "actual_function - $i"
    done
}

# Setting the value of the 'problematic' argument
some_string="\"five-1 five-2\""

# Calling the function with a collated set of arguments
wrapper_function "one two three four" "${some_string}"

虽然输出有些不同,但似乎完成了我想要做的事情:

1: Parameter count: 2
wrapper_function - one two three four
wrapper_function - "five-1 five-2"
2: Parameter count: 5
actual_function - one
actual_function - two
actual_function - three
actual_function - four
actual_function - "five-1 five-2"

我希望有人会发现这很有用。

相关内容