【问题标题】:Set case sensitive Windows environment variables in Perl在 Perl 中设置区分大小写的 Windows 环境变量
【发布时间】:2015-03-18 10:53:47
【问题描述】:

我正在尝试在 Perl 中设置一些区分大小写的 Windows 环境变量,以便在 shell 脚本中使用它们。

但是,当我尝试在使用 system 命令从 Perl 调用的 shell 脚本中使用小写的环境变量并使用 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!

有人知道这在 Windows 中是否可行(即如何设置环境变量 Titi 而不是 TITI)?

谢谢

【问题讨论】:

  • 您使用的是哪个系统 (OS)?在我的情况下(OS X 和 Linux)它可以工作(我只需要在脚本创建语句中引用美元)。例如。 system "echo echo TOTO='\$TOTO'> toto.sh";
  • 我得到:TOTO=0+0,Titi=Not toto!,TITI=
  • 我使用的是 Windows,很遗憾...我会更新问题。
  • Windows 没有sh。你在运行 Cygwin 吗?
  • 我正在运行 Msys。但我想 Cygwin 也会出现同样的问题。 => 在问题中添加

标签: windows perl shell msys


【解决方案1】:

以下内容应独立于大小写问题。

让我们看第一行:

system "echo echo TOTO=\$TOTO > toto.sh";

如果你打电话

echo echo TOTO=\$TOTO

在您的命令行上,输出将是:

echo TOTO=\$TOTO

这似乎是,你想要什么。

但是,您使用 system 调用的行首先由 perl 解释,因此您的转义 \$ 变为 $。

然后输出取决于 $TOTO 的当前值(在您在脚本中设置环境变量之前),这可能是空的。

您应该将所有这些系统调用更改为单引号:

 system 'echo echo TOTO=\$TOTO > toto.sh';

如果你这样做,你会得到以下输出:

TOTO=0+0
Titi=
TITI=not TOTO

Titi 是空的,因为你没有给它赋值。

【讨论】:

  • 感谢您花时间写这么长的答案。但是,我不同意,因为我想发送到命令行“echo TOTO=$TOTO”,所以对系统的调用是正确的。您的最后一个建议返回(至少在 Windows 上),如下:TOTO=$TOTO。但是,我确实可以将这一行修改为:“system 'echo echo TOTO=\$TOTO > toto.sh';”所以简化。我遇到的问题似乎与以大写形式存储的 Windows 环境变量有关。
  • 对不起,我在 linux 上测试过,使用 bash 作为 shell。在您的情况下,“sh”是什么?你有安装 Cygwin 吗?
【解决方案2】:

Windows 环境变量标识符与 Windows 文件一样不区分大小写。

TitiTITI 都是同一个变量的名称,其值可以通过 Perl 中的$ENV{TITI}$ENV{Titi} 访问。同样,命令行中的echo %TITI%echo %Titi% 将给出相同的结果。

如果您解释了为什么需要区分大小写的环境变量名称,那么我们或许可以为您提供帮助。

【讨论】:

  • 我尝试从使用小写字母的 shell 脚本中调用它们。我对 shell 脚本的访问权限有限,所以我尽量避免修改 shell 脚本。
  • shell 脚本是否使用相同变量名的大写和小写版本?如果不是,那么您不需要区分它们,但如果是,那么我认为您别无选择,只能修改脚本。你的sh 来自哪里?它在 Windows 上不是标准的。
  • 该脚本仅使用一个部分小写的版本(如 Titi)。我已经安装了 Msys 并从那里运行 shell。
  • Echo 可用于将环境变量存储在局部变量中。例如。 my $ti = `"echo %TITI%"`;
  • @Underverse:当整个事情都可以在 Perl 中使用my $ti = $ENV{TITI} 完成时,向echo 掏钱是没有意义的
【解决方案3】:

这似乎是不可能的:Windows 只会使用大写的变量。

我所做的方法是通过将变量替换为大写等效项来临时转换脚本,并在使用它们后将它们切换回以前的状态。

就我而言,我必须处理从 shell 脚本 Run_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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 2017-04-09
    相关资源
    最近更新 更多