我的意思是使用以下形式的 GNUenv
或 BSDenv
命令:
env [name=value ...] [utility [args ...]]
看起来没有办法value
部分转义特殊字符,但我不太确定如何env
实现解析value
部分。
我知道通过 shell 的功能有很多方法可以做到这一点,但我想在没有 shell 帮助的情况下传递文字字符串(有点像 execute env
by exec
)。也就是说,我需要找到某种带有换行符并由env
命令支持的文字字符串格式。例如:
env FOO=LITERAL_STRING ruby -e 'puts ENV["FOO"]'
这里LITERAL_STRING
应该包含一个带有换行符的文字字符串,并且env
应该理解这种格式。
使用上面的命令,预期的输出应该是:
hello
world
我想知道这是否可能。我会很感激你的帮助。
环境
env
我使用 BSD
env
,所以它无法打印版本。不知道man
能不能帮上忙:$ man env | tail -n1 BSD April 17, 2008 BSD
操作系统
$ sw_vers ProductName: macOS ProductVersion: 11.6 BuildVersion: 20G165
你的理解是不正确的。当您将内容存储
"hello\nworld"
到变量中时,\n
将按字面意思解释。仅当您调用printf
或echo
使用-e
标志之类的工具时,它们才会在打印到控制台时扩展这些反斜杠序列。在您的情况下,您希望将变量传递给扩展换行符的环境,建议为此在 bash 中使用ANSI C 样式引用
或者,如果可移植性是一个问题,一个简单的解决方案是将这些换行符放在您想要的位置
GNU和FreeBSD
env
有一个-S
("split") 选项[1],它在空格上分割它的参数,然后在结果字符串中解释很多转义,包括但不限于\n
:[1] 它的主要用途是用于
#! ...
shebang 行,但它也可以用在其他需要命令行的地方,但使用 ad-hoc 解析器而不是 shell 来解释它,就像-e
大多数基于 vte 的选项一样终端。该命令在执行时需要来自系统调用
env
的许多参数——就像任何命令一样。execve()
执行它的进程将执行以下操作:并且
env
,反过来,会做(通常在同一过程中):where
modified_environ
isenviron
but withvar=value
附加到它,或者如果已经有一个或多个以var=
in开头的字符串environ
,则它们中的第一个(至少)替换为var=value
.这些参数是以 NUL 结尾的字节数组,因此它们不能包含的唯一字节是 NUL 字节。这同样适用于名称和值都不能包含 NUL 字节的环境变量。
env
,在启动时,从头到尾处理其参数。开头的那些
-
将被视为选项。-
单独也被当成古形-i
来无视environ
。包含至少一个的选项(或
--
可用于标记选项结束)之后的选项=
将被视为 env var 字符串(放在modified_environ
上面)。第一个不包含=
字符的非选项参数被视为命令名称(它将作为第一个参数传递给命令,也用于在 中查找可执行文件的路径$PATH
)。之后的任何参数都将作为参数传递给命令,即使它们以字符开头
-
或包含=
字符。所以就
env
其本身而言,只有-
和=
字符是特殊的;-
仅在选项处理期间,并且=
仅在找到命令名称之前。为了能够传递以开头的环境变量名称
-
或以开头的命令名称-
,您可以使用--
:在几个
env
实现中,-
单独的跟随--
仍然不会被视为命令名称。因此,如果您想调用名为 的命令,则-
需要预先传递至少一个环境变量:(或使用
/path/to/-
or./-
代替-
并绕过$PATH
该命令的查找-
)。env
但是不允许您运行名称包含字符的命令,并且=
不能传递没有. 在这些情况下,无法逃脱角色。=
modified_environ
=
但是在您的情况下,除了 NUL 字节之外,就其本身而言
env
FOO=LITERAL_STRING
,没有任何字符LITERAL_STRING
会成为问题。env
现在,当用某种语言编写代码来执行该
env
命令时,该语言中可能存在无法按字面输入的字符。例如,在 中
perl
,你会这样做:将换行符表示为
\n
双引号内,但您也可以这样做:传递包含换行符的字符串。
在类 Bourne 的 shell 语言的语法中,换行符在单引号或双引号内时并不特殊(例如 的
q(...)
或qq(...)
引用运算符perl
),因此您可以这样做:"..."
在 C shell 中,或者在不是引用运算符的 rc shell 中,这将是另一回事。你
env FOO=LITERAL_STRING ruby -e 'puts ENV["FOO"]'
看起来像 shell 语言中的代码。该语法对于大多数 shell 都是有效的,因为几乎所有 shell 都将空格理解为单词分隔符和'...'
引用运算符。当您
exec
在开始时省略 时,shell 在子进程中运行该命令,然后等待该进程终止或挂起。如果那
env FOO=LITERAL_STRING ruby -e 'puts ENV["FOO"]'
是一种不允许按字面意思输入换行符(可能不是shell)也不允许使用某种形式的编码(\n
,,,%0a
...
)的语言,但显然支持'...'
像大多数shell一样作为引用运算符,除了BSD @UncleBillyenv -S
已经建议的技巧,您可以调用解释器或可以执行命令的语言,并允许以某种编码方式指定换行符,例如, , , , , ...perl
ruby
python
ksh93
zsh
bash
由于您已经拥有
ruby
:但是任何血统编程语言,包括
ruby
可以自己设置环境变量,所以你不需要env
:在值中使用文字换行符:
输出:
如果您
\n
想要将字符串转换为实际的换行符,请使用实用程序,例如printf
,就像在其他任何地方一样:env
在这方面并不特别(事实上,env
只看到真正的换行符,因为它在进程开始之前就被扩展了)。