首页 > 解决方案 > 如何避免将字符串参数分解为多个参数?

问题描述

我想将字符串参数传递给 Bash 过程。此过程在控制台上打印字符串并将副本打印到文件中。

在我的用例中,此文件将包含 Bash 脚本中所有已执行命令的列表,可用于以相同顺序重新运行所有指令。如果发生错误并且我需要将复制器脚本发送到 GitHub 上的开源项目,则需要这样做。它还将所有使用过的文件复制到一个目录中,以便以后创建 ZIP 文件。

所以,让我们谈谈 Bash 代码:

#! /bin/bash
open() {
    local File=$1
    exec 3<> "$File"
}

close() {
    exec 3>&-
}

procedure1() {
    echo "$1"
    echo "echo \"$1\"" >&3
}

procedure2() {
    echo "$1" "$2"
    echo "echo \"$1\" \"$2\"" >&3
}

procedure3() {
    echo "$@"
    echo "echo \"$@\"" >&3
}

# ==============================================================================
OUTPUT_FILE="output.sh"

Program_A="foo"
Paramater_A=(
    --spam
    --egg=4
)

Program_B="bar"
Paramater_B=(
    --ham
    --spice=4
)

open $OUTPUT_FILE

echo "$Program_A -a ${Paramater_A[@]}"
echo "$Program_B -b ${Paramater_B[@]}"
echo
procedure1 "$Program_A -a ${Paramater_A[@]}" "$Program_B -b ${Paramater_B[@]}"
procedure2 "$Program_A -a ${Paramater_A[@]}" "$Program_B -b ${Paramater_B[@]}"
procedure3 "$Program_A -a ${Paramater_A[@]}" "$Program_B -b ${Paramater_B[@]}"

close

echo
echo -e "\e[33m========================================\e[0m"
echo -e "\e[33mReading output file from disk\e[0m"
echo -e "\e[33m========================================\e[0m"
echo
cat $OUTPUT_FILE

控制台输出是这样的:

$ ./test.sh
foo -a --spam --egg=4
bar -b --ham --spice=4

foo -a --spam
foo -a --spam --egg=4
foo -a --spam --egg=4 bar -b --ham --spice=4

========================================
Reading output file from disk
========================================

echo "foo -a --spam"
echo "foo -a --spam" "--egg=4"
echo "foo -a --spam --egg=4 bar -b --ham --spice=4"

所以我看到的是,它".... ${Parameter_A[@]} ..."包含在一个字符串中,但是将字符串分成多个字符串。这就是为什么$1在过程中包含包含第一个参数值的字符串。

如何将所有参数嵌入单个字符串而不将其分解为多个字符串?

$@用于打印所有文本,因为它包含传递给过程的所有参数。但是,这不是我的解决方案,因为我无法区分字符串何时$2开始,或者换句话说,有多少部分属于$1.

标签: stringbashvariable-expansion

解决方案


按照Cyrus的建议,我使用shellcheck.net来检查我的 Bash 脚本。

这是检查器的输出:

$ shellcheck myscript

Line 24:
    echo "echo \"$@\"" >&3
                 ^-- SC2145: Argument mixes string and array. Use * or separate argument.

Line 33:
    --egg=4
    ^-- SC2191: The = here is literal. To assign by index, use ( [index]=value ) with no spaces. To keep as literal, quote it.

Line 39:
    --spice=4
    ^-- SC2191: The = here is literal. To assign by index, use ( [index]=value ) with no spaces. To keep as literal, quote it.

Line 44:
echo "$Program_A -a ${Paramater_A[@]}"
                    ^-- SC2145: Argument mixes string and array. Use * or separate argument.

Line 45:
echo "$Program_B -b ${Paramater_B[@]}"
                    ^-- SC2145: Argument mixes string and array. Use * or separate argument.

Line 47:
procedure1 "$Program_A -a ${Paramater_A[@]}" "$Program_B -b ${Paramater_B[@]}"
                          ^-- SC2145: Argument mixes string and array. Use * or separate argument.
>>                                                          ^-- SC2145: Argument mixes string and array. Use * or separate argument.

Line 48:
procedure2 "$Program_A -a ${Paramater_A[@]}" "$Program_B -b ${Paramater_B[@]}"
                          ^-- SC2145: Argument mixes string and array. Use * or separate argument.
>>                                                          ^-- SC2145: Argument mixes string and array. Use * or separate argument.

Line 49:
procedure3 "$Program_A -a ${Paramater_A[@]}" "$Program_B -b ${Paramater_B[@]}"
                          ^-- SC2145: Argument mixes string and array. Use * or separate argument.
>>                                                          ^-- SC2145: Argument mixes string and array. Use * or separate argument.

它表明@需要将 used 更改为*@包含在双引号中扩展为包含在双引号中的每个数组元素,而*扩展为字符串。


推荐阅读