取消一个命令的环境变量


24

我可以使用的特定值ENV_VAR=value command运行。等于unset的作用是什么?commandENV_VARENV_VARcommand


7
除了:command是一个不幸的占位符选择,因为实际上一个内置命令使用该名称。mycommandsomecommand或这种可能是更好的习惯,就搞定了。
查尔斯·达菲

@CharlesDuffy,我通常使用cmd它。
斯特凡Chazelas

Answers:


35

除了使用-i可擦除整个环境的选项外,POSIX env不提供任何方法来取消设置变量。

但是,通过一些env实现(busybox至少包括GNU,'和FreeBSD),您可以执行以下操作:

env -u ENV_VAR command

这可以ENV_VAR从环境中删除变量的每个实例(请注意,尽管它不适用于名称为空的环境变量(env -u ''根据实现的不同,它会产生错误或无效,即使全部接受env '=value',也可能是一个限制)unsetenv()POSIX要求C函数引起的返回空字符串错误,而putenv()))没有这种限制。

可移植地(在POSIX shell中),您可以执行以下操作:

(unset -v ENV_VAR; exec command)

(请注意,在某些外壳程序中,using exec可以更改command运行的程序:例如,在文件系统中而不是函数或内置程序中运行(并且alias显然会绕过扩展),就像env上面那样。在这种情况下,您可以忽略它) 。

但这不适用于名称不可映射到外壳变量mksh的环境变量(请注意,某些外壳程序无论如何都会在启动时将这些变量从环境中删除),或已标记为只读的变量。

-v对于Bourne shell和bashunset-v能够取消设置ENV_VAR 的功能如果没有变量这个名字。除非您通过该-f选项,否则其他大多数Shell都不会取消设置功能。(不太可能在实践中有所作为)。

(另外注意的错误/不好的特性的bash/ mksh/ yashunset,在某些情况下可以不取消设置变量,但显示在可变外部范围

如果perl可用,您可以执行以下操作:

perl -e 'delete $ENV{shift@ARGV}; exec @ARGV or die$!' ENV_VAR command

即使对于具有空名称的环境变量也可以使用。

现在,如果您要为内置函数或函数更改环境变量并且不希望它们在子shell中运行,那么所有这些将不起作用,例如bash

env -u LANG printf -v var %.3f 1.2 # would run /usr/bin/printf instead
(unset -v LANG; printf -v var %.3f 1.2) # changes to $var lost afterwards

(这里将LANG设置为一种误导方法,以确保.使用并理解为小数点分隔符。LC_ALL=C printf...为此,最好使用该方法)

在某些外壳程序中,您可以使用函数为变量创建局部作用域:

without() {
  local "$1" # $1 variable declared as initially unset in bash¹
  shift
  "$@"
}
without LANG printf -v var %.3f 1.2

使用zsh,您还可以使用匿名函数:

(){local ENV_VAR; command}

这种方法在某些外壳程序(例如基于Almquist外壳程序的外壳程序)中local不起作用,它们不会将变量声明为初始未设置(而是继承值和属性)。在这种情况下,您可以这样做local ENV_VAR; unset ENV_VAR,但不要在mkshyashtypeset而不是local针对那个)中这样做,因为那样行不通,unset只能取消local

¹另外请注意,在中bash,本地ENV_VAR(即使未设置)将保留导出属性。因此,如果command是一个为赋值的函数ENV_VAR,则该变量将在随后调用的命令环境中可用。unset ENV_VAR会清除该属性。或者,您也可以使用local +x ENV_VAR这样做,以确保状态良好(除非该变量已声明为只读,但在中您无能为力bash)。


1
这是一个单独的问题,但是到底什么是空名称的环境变量?您将如何使用它-即使是某种形式的利用?您是否不必编写一个读取环境并专门查找类似内容的程序?

@Joe,例如尝试env '=foo' python -c 'import os; print os.environ[""]'。我不希望很多人愿意设置这样的变量。
斯特凡Chazelas

9

据我所知,没有直接的对等物。您可以使用一个子shell:

(unset ENV_VAR; exec command)

(unset ENV_VAR; exec somecommand)如果您想在效率上等同于原始版本(通过使用subshel​​l)。实际上,这增加了一个额外的叉子。
查尔斯·达菲

1
@Charles的确如此,尽管有些shell自动执行此操作,因为这command是子shell调用中的最后一个命令。
斯蒂芬·基特

+1,因为这种方式易于键入以进行交互使用。我使用subshel​​l一次性更改shell环境,而不是记住它env -u
彼得·科德斯

0

您可以使用 ENV_VAR= command

这实际上并没有取消设置变量,但是在许多情况下可能有用(shell脚本通常仅用于test -n检查是否设置了变量):

$ export ENV_VAR=foo
$ mycommand
ENV_VAR: foo
$ ENV_VAR=bar mycommand
ENV_VAR: bar
$ ENV_VAR= mycommand
ENV_VAR: 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.