【问题标题】:Weird environment variables that aren't in Perl's ENV hash不在 Perl 的 ENV 哈希中的奇怪环境变量
【发布时间】:2019-09-09 04:17:12
【问题描述】:

Perl 可以访问一些环境变量:

> echo $HOST
xtt006
> perl -E 'say $ENV{HOST}'
xtt006
> perl -E 'say `echo \$HOST`'
xtt006

但显然还有另一类环境变量不在 ENV 哈希中:

> echo $env
opsd
> perl -E 'say $ENV{env}'
(no response from Perl)
> perl -E 'say `echo \$env`'
(no response from Perl)

那是怎么回事? Perl 是否有另一种技术可以获取 $env 的值?

【问题讨论】:

  • 不,我在运行“env”时看不到它。但我确实看到了“echo $env”。
  • 是的,我应该。有人告诉我“你通过输入 'echo $foo' 来显示环境变量 'foo' 的值,显然这解释过于简单。env 是一个“本地 shell 变量”,如下 zdim 所示?
  • "too simplistic ..." --- 事实上,echo $foo 显示 any shell 变量的值,本地或环境。但是env(或printenv)只显示环境变量(全部)。

标签: perl environment-variables


【解决方案1】:

尝试从 shell 中exporting 你的变量。这会将它从 shell 的变量列表移动到所有子进程都可以看到的环境中。

export env
perl -E 'say $ENV{env}'

这应该让它显示出来。

【讨论】:

  • 在 bash 中,printenv 将列出所有导出的环境变量(将由子进程继承),set 将列出所有变量,包括 shell 中的本地环境变量。
  • 我们在这里使用 csh,我得到“导出:找不到命令”。 /bin/env 显示了我的大部分(但不是全部)环境变量。 "echo $env" 返回 opsd,而 "env | grep env" 什么也不返回。
【解决方案2】:

来自%ENV in perlvar (我的重点)

哈希 %ENV 包含您当前的环境

环境继承自启动 Perl 进程的进程,这里是 shell。

但是,shell variables 可以是本地,它不会传递给子进程,也可以是全局的,形成环境并由子进程继承。全局的大部分是在启动时从配置文件中读取的,但如果要稍后添加,则需要exported

如上例中创建的变量仅对当前 shell 可用。它是一个局部变量:当前 shell 的子进程不会知道这个变量。为了将变量传递给子shell,我们需要使用export 内置命令导出它们。导出的变量称为环境变量。设置和导出通常一步完成:

export VARNAME="value" 

(我的重点)  根据您的描述,$env 似乎被添加为局部变量(带有set),然后还需要导出(export env)以便在单行中看到.

环境变量可以用envprintenv 列出,而set 列出所有变量,包括本地变量和环境变量。


以上是指bash shell。 “环境”的概念在其他 shell 中是相同的,同样的推理也适用于那里;对于要在子进程中看到的变量,我们需要将其设为全局(“环境变量”)。不同之处在于如何做到这一点。

csh/tcsh使用

setenv env "value"

而不是set var = "value",会创建一个局部变量。


除了使用全局(“环境”)变量而不是本地变量之外,还可以将变量传递给 Perl 代码。请参阅 this postthis post 以获取使用单行代码执行此操作的示例。如果调用了实际脚本,则使其带有参数;标准的也是最好的方法是Getopt::Long

这不是对用户的特殊要求;他们使用您的脚本并且需要适当地调用它。

【讨论】:

  • @user3358338 已针对 bash 以外的 shell 进行了更新
  • 有没有相当于“export”的csh?即使有,这也不是一个很好的解决方案......我不希望我的 Perl 脚本的用户在运行脚本之前必须“导出 env”。
  • @user3358338 不(我不知道)——在 csh/tcsh 中是 setsetenv。至于用户会做什么......如果他们希望您的脚本了解变量,他们必须将其设为全局或将其传递给脚本。你能再解释一下吗?
  • 我不是给 $env 赋予 opsd 价值的人。我只是登录并在那种情况下找到它。正如你所说,我不怀疑它是用set env = "opsd" 完成的。我希望我的 Perl 脚本能够使用该值。我觉得奇怪的是 csh 可以访问该值(使用 echo $env),但是从可以访问该值的 csh 启动的 Perl 无法访问该值。
  • @user3358338 是的,明白了。但是set env =... 创建了一个 local 变量,从该脚本派生的进程看不到该变量。这就是来龙去脉。可以:(1)改为全局(2)调用脚本并将值传递给它。我认为,这完全有道理。他们调用你的脚本,并在适当的时候调用它。
【解决方案3】:

就像 Perl 有私有变量 (my $x) 和环境变量 ($ENV{Y}) 一样,shell 也有。

$ perl <<'.'
my $x = "x";
$ENV{Y}="Y";
system 'echo "<$x> <$Y>"';
.
<> <Y>

$ sh <<'.'
x=x
export Y=Y
perl -le'print "<$x> <$ENV{Y}>";'
.
<> <Y>

$ csh <<'.'
set x x
setenv Y Y
perl -le'print "<$x> <$ENV{Y}>";'
.
<> <Y>

支持私有变量是一件好事,而不是一件奇怪的事。

在您的示例中,$HOST 是一个环境变量(按惯例大写),而$env 是一个私有变量(按惯例小写)。


shbash

这些 shell 使用相同的机制来分配私有变量和环境变量。

要创建环境变量,可以使用export 将私有变量提升为环境。

VAR=val
export VAR
perl -e'...$ENV{VAR}...'

export VAR
VAR=val
perl -e'...$ENV{VAR}...'

晋升和分配可以结合。

export VAR=val
perl -e'...$ENV{VAR}...'

上述方法改变了 shell 的环境,以及它创建的所有后续子项。以下方法可用于改变特定儿童的环境:

VAR=val perl -e'...$ENV{VAR}...'

这种方法也可以用来有效地提升私有变量:

var=val
VAR="$var" perl -e'...$ENV{VAR}...'

cshtcsh

这些 shell 使用不同的语法来设置私有变量和环境变量。

要设置私有变量,可以使用set

set var val

要设置环境变量,可以使用setenv

setenv VAR val
perl -e'...$ENV{VAR}...'

上述方法改变了 shell 的环境,以及它创建的所有后续子项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 2015-03-26
    • 2020-02-13
    • 2012-05-12
    相关资源
    最近更新 更多