在Perl中设置区分大小写的Windows环境变量
我试图在Perl中设置一些区分大小写的Windows环境变量,以便在shell脚本中使用它们 但是,我注意到,当我尝试在一个shell脚本中以小写形式使用环境变量时,这些环境变量都是大写的,该脚本由Perl通过在Perl中设置区分大小写的Windows环境变量,windows,perl,shell,msys,Windows,Perl,Shell,Msys,我试图在Perl中设置一些区分大小写的Windows环境变量,以便在shell脚本中使用它们 但是,我注意到,当我尝试在一个shell脚本中以小写形式使用环境变量时,这些环境变量都是大写的,该脚本由Perl通过system命令调用,并使用Msys运行 例如,以下脚本: #!perl system "echo echo TOTO=\$TOTO > toto.sh"; system "echo echo Titi=\$Titi >> toto.sh"; system "echo
system
命令调用,并使用Msys运行
例如,以下脚本:
#!perl
system "echo echo TOTO=\$TOTO > toto.sh";
system "echo echo Titi=\$Titi >> toto.sh";
system "echo echo TITI=\$TITI >> toto.sh";
$ENV{'TOTO'}="0+0";
$ENV{'Titi'}="Not toto!";
system("sh toto.sh");
返回(在Msys中运行时)以下输出:
TOTO=0+0
Titi=
TITI=Not toto!
TOTO=0+0
Titi=
TITI=not TOTO
是否有人知道这在Windows中是否可行(即如何设置环境变量Titi
,而不是Titi
)
谢谢以下内容应与套管问题无关 让我们看第一行:
system "echo echo TOTO=\$TOTO > toto.sh";
如果你打电话
echo echo TOTO=\$TOTO
在命令行上,输出将是:
echo TOTO=\$TOTO
这似乎是你想要的
但是,您使用系统调用的行首先由perl解释,因此转义的\$变成$
然后,输出取决于$TOTO的当前值(在脚本中设置环境变量之前),该值可能为空
您应该将所有这些系统调用更改为单引号:
system 'echo echo TOTO=\$TOTO > toto.sh';
如果执行此操作,将获得以下输出:
TOTO=0+0
Titi=
TITI=Not toto!
TOTO=0+0
Titi=
TITI=not TOTO
Titi为空,因为您没有给它赋值。Windows环境变量标识符与Windows文件一样,大小写独立
Titi
和Titi
都是同一变量的名称,可以通过Perl中的$ENV{Titi}
或$ENV{Titi}
访问其值。同样,命令行上的echo%TITI%
和echo%TITI%
也会给出相同的结果
如果您解释为什么需要区分大小写的环境变量名,我们可能会帮助您。这似乎是不可能的:Windows将只使用大写变量 我所做的方法是临时转换脚本,将变量替换为大写等效变量,并在使用它们之后将它们切换回以前的状态 在我的例子中,我必须处理从shell脚本
Run\u Session.sh
导出的变量。我创建了一个Perl脚本来执行大写替换,这就是结果
###############################
## SUBROUTINE uc_variables ##
#-----------------------------#
# This subroutine convert the environment variables exported
# by the top level script to upper case, and can revert the operation.
#
# Input:
# -----
# $mode: "ON" (default) or "OFF"
#
# Output:
# ------
# N/A
#-----------------------#
#########################
sub uc_variables {
my $mode=shift;
chdir $Bin;
if ($mode eq "OFF") {
foreach my $bak (glob "{*,*/*}.sh.bak") {
(my $orig = $bak)=~s/\.bak//;
move($bak,$orig);
}
} else {
#Check if back-up already exists
uc_variables("OFF") if (-e "Run_Session.sh.bak");
#List variables to update
my %uc_var;
open RUN_SESSION,"<Run_Session.sh" or die "Error while reading Run_Session.sh ($!)\n";
map { /export\s+(\w*[a-z]\w*)/ and ($uc_var{$1}=uc($1))=~s/Directory/DIR/i } <RUN_SESSION>;
close RUN_SESSION;
#Replace variables
foreach my $shell (glob "{*,*/*}.sh") {
#Back-up
copy($shell,"$shell.bak");
#Read data
open SHELL,"<$shell" or die "Error while reading $shell ($!)\n";
my $SHELL = join("", <SHELL>);
close SHELL;
#Replace
map { $SHELL=~s/$_/$uc_var{$_}/g } keys %uc_var;
#Print
open SHELL,">$shell" or die "Error while writing in $shell ($!)\n";
print SHELL $SHELL;
close SHELL;
}
}
} #end of uc_variables
###############################
##子程序uc_变量##
#-----------------------------#
#此子例程转换导出的环境变量
#由顶层脚本改为大写,并可以还原操作。
#
#输入:
# -----
#$mode:“开”(默认)或“关”
#
#输出:
# ------
#不适用
#-----------------------#
#########################
子uc_变量{
我的$mode=shift;
chdir$Bin;
如果($mode eq“OFF”){
foreach my$bak(glob“{*,*/*}.sh.bak”){
(my$orig=$bak)=~s/\.bak/;
移动($bak,$orig);
}
}否则{
#检查备份是否已经存在
uc_变量(“关闭”)如果(-e“Run_Session.sh.bak”);
#列出要更新的变量
我的%uc_var;
在写入$shell($!)时打开运行会话“$shell”或die”错误\n;
打印SHELL$SHELL;
封闭外壳;
}
}
}#uc#U变量结束
您使用的是哪种系统(操作系统)?在我的情况下(OSX和Linux),它是有效的(我只需要在脚本创建语句中引用美元)。例如,系统“echo-echo-TOTO='\$TOTO'>TOTO.sh”;我得到:TOTO=0+0,Titi=nottoto!,TITI=不幸的是,我使用Windows。。。我将更新问题。Windows没有sh
。你在运行Cygwin吗?我在运行Msys。但我想同样的问题也会发生在Cygwin身上在问题中补充道:谢谢你花时间写这么长的答案。但是,我不同意,因为我想发送到命令行“echo TOTO=$TOTO”,所以对系统的调用是正确的。您的上一个建议返回(至少在Windows上),如下所示:TOTO=$TOTO。不过,我确实可以将这行代码修改为:“system'echo-echo-TOTO=\$TOTO>TOTO.sh';”所以请简化。我遇到的问题似乎与Windows环境变量存储为大写有关。很抱歉,我在linux上进行了测试,使用bash作为shell。在你的情况下,“sh”是什么?您是否安装了Cygwin?我尝试从使用小写字母的shell脚本调用它们。我对shell脚本的访问权限有限,因此我尽量避免修改shell脚本。shell脚本是否使用相同变量名的大小写版本?如果没有,那么您不需要区分它们,但是如果有,那么我认为您除了修改脚本之外别无选择。你的sh
来自哪里?这不是Windows上的标准版本。脚本只使用一个部分小写的版本(如Titi)。我已经安装了Msys并在那里运行shell。Echo可用于将环境变量存储在局部变量中。例如,my$ti=`“echo%TITI%”
@Underverse:当整个事情都可以在Perl中用my$ti=$ENV{TITI}
完成时,向echo抛出代码是毫无意义的