bash -c 命令解析

bash -c 命令解析

bash 联机帮助页对该选项的说明如下-c

-c 如果存在 -c 选项,则从第一个非选项参数 command_string 读取命令。如果 command_string 之后有参数,则第一个参数将分配给 $0,任何剩余参数将分配给位置参数。对 $0 的赋值设置了 shell 的名称,该名称用于警告和错误消息。

从上面我希望下面的代码在其输出中是等效的:

# or possibly (`bash -c date date +%z`)
$ bash -c date +%z
Wed Oct 18 10:02:47 PM UTC 2023
$ date +%z
+0000
# The first command gives the output of `date` without the format specifier.

然而,我的 bash(GNU bash,版本 5.2.15)似乎从未评估额外的命令行位置参数。选项后第一个参数之后的所有内容-c都会被默默丢弃。也许我误解了手册页。

如何将多个参数bash -c作为单词(底层的 arg 向量)而不是一个字符串 ( bash -c "date +%z") 传递给命令?这可能吗?

语境

我问这个问题的目的是了解 bash 如何期望传递命令参数,以便通过execve()另一个程序(包装外壳)中的函数系列之一将它们正确地输入到 bash 中。

答案1

第一个参数分配给 $0

$0 不是第一个参数,$1 是。此外,您需要使用命令字符串中的参数。

bash -c 'date "$1"' zero +%z

答案2

这里,

bash -c date +%z

-cis之后的第一个非选项参数date,是 Bash 将解析和运行的 shell 代码。之后的参数被分配给 shell 或脚本名称$0(此处为+%z),然后是位置参数$1$2...(此处全部未设置)。

该字符串+%z不会被丢弃,但由于该命令date不使用$0(或$1等),因此它不会影响 shell 的操作。但是,如果 shell 必须打印错误消息,则会使用它。例如:

$ /bin/bash -c datexxx +%z
+%z: datexxx: command not found

该脚本找不到该命令datexxx,因此它确实输出了一条错误消息,并在其前面加上了我们为脚本指定的名称 ( +%z)。


要使用后面的参数-c和 shell 代码,您需要传递一个使用脚本名称$0或位置参数的命令$1...,例如:

% bash -c 'echo "script name: $0", first arg: "$1"' foo bar doo
script name: foo, first arg: bar

不过,如果您想按原样将参数列表传递给另一个命令,您宁愿使用"$@"(带引号)将所有位置参数作为不同字段扩展(就像您用于"$1" "$2" ...所有设置的位置参数一样)。

所以(假设 GNU 日期为-d):

% bash -c 'date "$@"' my-inline-script +"%F %T" -d '1 Jan 2001'
2001-01-01 00:00:00

(同样,只有当 shell 需要打印错误消息时my-inline-script才会$0使用它。上面的示例应该说明为什么在那里放置一些描述性内容是有意义的。无论如何,我们需要向那里传递一些$0之前填充的值位置参数。)

答案3

的参数-c必须是一个字符串。其余的将是参数$0, $1, ...

例子:

bash -c 'echo name=$0 params=$*' a b c

输出:name=a params=b c

此处单引号的使用很重要。因为它不允许当前 shell 填充等的值$0$*

如果您想从当前 shell 中获取值,请使用双引号。例如:

X=42
bash -c "echo $X"

输出:42

混合单引号和双引号也是可能的。只要后面的参数仍然-c是一个字符串。

X=42
bash -c "echo $X"' 0=$0 $*' 

输出:(42 0=bash 这里$0默认为bash

相关内容