我有一个参数列表和三个进程:
bash_script -> child -> grandchild
参数列表针对的是孙子。我可以修改所有三个进程。祖父脚本为自己获取一个参数。
以下是将剩余参数传递给孙子的正确方法吗?
#!/usr/bin/env bash
# This is the grandfather
first_arg="$1"
shift 1;
export MY_ARGS="$@"
我稍后在子进程中“传播”环境变量,作为调用孙子进程的命令的一部分,如下所示:
grandchild --foo "$MY_ARGS" # append $MY_ARGS as arguments to foo
答案1
在脚本中,不应将数组降级为字符串。环境变量及其值是一个简单的key=value
对,其中key
和value
都是字符串。将位置参数降级为简单的字符串(通过连接)将很难保持它们之间的分离,并且当您最终想要使用它们时很难正确引用它们。
相反,传递您想要传递给命令行上的下一个脚本的位置参数(命令行参数)。
#!/bin/bash
first_arg=$1
shift
# later ...
./my_other_script "$@"
在另一个脚本中:
#!/bin/bash
# use "$@" here
foo --bar "$@"
答案2
编辑:看来你不能在 bash 中导出数组。您可能需要导出一个设置数组或类似内容的函数。
您应该使用数组,否则带有空格的参数将扩展到多个单词。
export MY_ARGS=("$@")
foo --bar "${MY_ARGS[@]}"
答案3
我不确定为什么人们对这个问题感到困惑,但也许这个问题令人困惑,这对我来说似乎很有效:
my_args_array=("$@")
export MY_ARGS="${my_args_array[@]}"
然后我们只需MY_ARGS
像这样使用:
foo --bar $MY_ARGS
笔记正如@Kusalananda 指出的:这将失败如果原始参数中有空格。在这种情况下,最好使用$@
, 而不是环境变量通过子进程传递参数。
答案4
一般的答案是这样的。您可以使用以下方式传递参数:
- 命令行位置参数
- 环境变量
- 您的操作系统上可用的任何 IPC(进程间通信)
只关注前两个,
- 位置参数是最自然的方式。这涉及 的可能编辑和进一步传输
"$@"
,它代表所有当前定义的位置参数。这必须在流程层次结构的所有阶段上完成。 环境变量不像位置参数那么简单,因为它们以键值对的形式出现。即使您以这种方式传递值,您也需要键来获取它们。只要它们不是唯一的环境变量,在没有充分考虑的情况下我不会假设它们。但这个方法是可行的。您所需要做的就是在感兴趣的各方之间共享密钥。键本身可以基于模式。以下是如何完成此操作的示例。
有两个脚本 -
p.bash
和c.bash
。p
代表父母,而c
代表孩子。它们可以被中介分开,只要中介不会删除通过环境传输的值。为简单起见,这两个脚本在p.bash
调用中具有直接连接c.bash
。这是
p.bash
:#!/bin/bash shift #consume the first argument #parse and export the other arguments prefix=abcdef_ i=0 for a in "$@"; do export "$prefix""$i"="$a" ((i++)) done ./c.bash
这是
c.bash
:#!/bin/bash #consume the env arguments prefix=abcdef_ env | grep ^"$prefix"
这是执行过程:
$ ./p.bash arg "1 2" "3 4" "5 6" abcdef_0=1 2 abcdef_1=3 4 abcdef_2=5 6
我将解释两行,每个脚本各一行。
第一个是发电机,
export "$prefix""$i"="$a"
export
abcdef_0
使用、等形式的变量填充环境abcdef_1
。现在子进程可以在其环境中找到它们。 (只要它们没有被某些中间人重置。)env | grep ^"$prefix"
孩子就是消费者。env
列出环境变量,并grep
过滤掉与负责相关传输的前缀无关的所有行。一旦您了解了这里发生的情况,您应该能够访问传输的变量并在后代进程中使用它们。