如何避免将字符串参数分成多个参数?

时间:2018-11-24 18:51:32

标签: string bash variable-expansion

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

在我的用例中,该文件将包含Bash脚本中所有已执行命令的列表,可用于以相同顺序重新运行所有指令。如果发生错误并且我需要将 reproducer 脚本发送到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中有多少部分。

1 个答案:

答案 0 :(得分:0)

根据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.

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