【问题标题】:how to put all command arguments in one variable如何将所有命令参数放在一个变量中
【发布时间】:2015-02-16 13:48:27
【问题描述】:

我想执行一个需要 3 个参数的 shell 脚本。

参数号 2 包含一个带空格的字符串

我想将所有参数放在一个变量中,如下所示:

Linux:~# kk="\"111\" \"222 222\" \"333\""
Linux:~# echo $kk
"111" "222 222" "333"

现在如果我调用一个函数:

func() {
  echo ---$1---
  echo ---$2---
  echo ---$3---
}

以这种方式使用 $kk 变量

func $kk

然后它会返回

Linux:~# func $kk
---"111"---
---"222---
---222"---

我期待得到这个结果

---111---
---222 222---
---333---

不使用eval如何解决这个问题?

我知道eval 解决了这个问题,但我不想使用它(因为如果我执行多次这样的调用需要时间)。

【问题讨论】:

  • 如果没有eval,您将无法做到这一点。详情请见mywiki.wooledge.org/BashFAQ/050
  • 如果目标是 bash 而不是 POSIX,可以用数组来完成(为什么用两个不同的 shell 标记?)
  • ...即使在不支持正确数组的 ash 中,也可以使用函数的命令行参数作为临时安全数组存储来完成此操作(或完全覆盖全局 "$@",如果一个人不需要它,也不想使用函数来确定范围)。
  • 顺便说一句,将多个参数放在一个标量变量中是不可能的(没有显式解析),原因很简单:标量变量可以存储 NUL 以外的任何值。一个参数同样可以存储除 NUL 之外的任何值。因此,没有办法判断"111" "222 222" "333" 是否意味着正好是一个包含文字引号的参数,四个包含文字引号但在空格上拆分的参数,或者三个不带引号的参数——但是对扩展施加解析规则将是老鼠的安全漏洞的巢穴,所以 Not Doing It 更安全,因此 shell 的行为也是如此。
  • “我想将所有参数放在一个像这样的变量中”......不,你没有。真的。你想要做的是重新设计其他地方所做的假设,让你认为你想要这样做......

标签: linux shell ash


【解决方案1】:

OP 最初标记了问题,然后删除了该标记。请参阅 Charles Duffy 的 POSIX shell 解决方案的最佳答案!下面的解决方案使用数组,仅适用于


你不应该把你的数据放在这样的字符串中,而应该放在一个数组中。顺便说一句,您的函数中缺少一些引号:

func() {
    echo "---$1---"
    echo "---$2---"
    echo "---$3---"
}

或者更好(printf 优于 echo):

func() {
    printf -- '---%s---\n' "$1"
    printf -- '---%s---\n' "$2"
    printf -- '---%s---\n' "$3"
}

$ kk=( "111" "222 222" "333" )
$ func "${kk[@]}"

很乐意打印:

---111---
---222 222---
---333---

您甚至可以在参数中包含换行符等:

$ kk=( $'one\none' "222 222" $' *   three\nthree' )
$ func "${kk[@]}"
---one
one---
---222 222---
--- *   three
three---

【讨论】:

  • 嘿等等,bash 标签突然从问题中消失了……这适用于bash
  • 是的,我删除了。很抱歉把它放在开头,但我正在寻找灰烬的解决方案
  • 肉(直到阵列演示)完全可以移植到其他 Bourne 家族的 shell。
【解决方案2】:

如果特性(如数组)没有使 bash 比 POSIX sh 更具表现力,那么就没有理由添加它们。 :)

也就是说,您可以根据需要覆盖 "$@" 来解决它:

set -- 111 "222 222" 333
printf '%s\n' "$@"

...将打印...

111
222 222
333

如果您需要逐步构建参数列表,您可以多次调用set,并将"$@" 作为第一个参数(确保您遵守引号!):

set -- 111
set -- "$@" "222 222"
set -- "$@" 333
printf '%s\n' "$@"

...将打印...

111
222 222
333

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-19
    • 1970-01-01
    • 2019-06-11
    • 2023-02-18
    • 2021-08-26
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多