【问题标题】:How do I evaluate shell variables in a string?如何评估字符串中的 shell 变量?
【发布时间】:2011-03-30 10:42:12
【问题描述】:

在我的 Perl 脚本中,我得到了可能包含环境变量的文件路径字符串,例如$FONTS/test.ttf$TMP/file.txt

我现在想像这样打开这些文件:

open my $handle, "<$filename" or die $!;

我现在如何在 open 调用之前扩展环境变量,例如bash shell 可以吗?

【问题讨论】:

标签: perl


【解决方案1】:

如果设置了环境变量,可以使用简单的替换:

$filename =~ s/\$(\w+)/$ENV{$1}/g;

【讨论】:

  • 简洁明了 - 和以往一样,错误处理会把它搞砸。具体来说,如果引用的环境变量之一没有设置,你充其量只会得到一个意想不到的路径;您可能还会收到有关从 Perl 访问未定义变量的警告。尽管还有其他的 shell 表示法(如 ${TMP}),但它们很少用于会出现问题的上下文中。
  • @Jonathan,bash 的标准行为是将空字符串替换为缺少的变量,因此此代码确实以 OP 要求的方式处理该错误情况。我同意我在脚本中大量使用 ${FOO:?} 来强制 bash 在未设置的变量上抛出错误的备用 shell 符号。
  • 我将其更新为 s/\$\{?(\w+)\}?/$ENV{$1}/ 以支持备用花括号格式。
【解决方案2】:

为什么不这样做:

$filename =~ s/\$\{(\w+)\}/$ENV{$1}/g;
$filename =~ s/\$(\w+)/$ENV{$1}/g;

【讨论】:

    【解决方案3】:

    下面的内容要冗长得多,但它 似乎可以正确处理 $FOO${FOO} 语法。

    #!/usr/bin/env perl
    
    use warnings;
    use strict;
    
    my $filename = $ARGV[0];
    print(" GIVEN: <$filename>\n");
    my $expanded = '';
    my @parts = split(/(\$\w+)|(\${\w+})/, $filename);
    foreach my $seg (@parts)
      {
        next if (not defined($seg));
        $seg = ($ENV{$1} || '')  if ($seg =~ m/\${?(\w+)}?/);
        $expanded .= $seg;
      }
    
    print("IS NOW: <$expanded>\n");
    print(`echo "  ECHO: <$filename>"`);  # How the shell did it.
    

    这是一个示例运行...

    $ ./expand '$TERM ---${TERM}--- ===${FOO}=== $FOO'
     GIVEN: <$TERM ---${TERM}--- ===${FOO}=== $FOO>
    IS NOW: <xterm-color ---xterm-color--- ====== >
      ECHO: <xterm-color ---xterm-color--- ====== >
    $
    

    在这个版本中,未定义的符号被替换为空字符串, 像贝壳。但在我的应用程序中,我宁愿保留未扩展的 无效的符号使人们更容易看到出了什么问题。 此外,如果您搞砸了支架匹配,外壳将 给你一个“错误的替换”错误,但在这里我们将返回 带有损坏符号的字符串仍然存在。

    【讨论】:

      【解决方案4】:

      对不起,你错了。

      要在 perl 中使用 SHELL 变量,正确的语法是:$ENV{variable}

      带有彩色 GCC 输出函数的示例:

      n=$(tput setaf 0)
      r=$(tput setaf 1)
      g=$(tput setaf 2)
      y=$(tput setaf 3)
      b=$(tput setaf 4)
      m=$(tput setaf 5)
      c=$(tput setaf 6)
      w=$(tput setaf 7)
      N=$(tput setaf 8)
      R=$(tput setaf 9)
      G=$(tput setaf 10)
      Y=$(tput setaf 11)
      B=$(tput setaf 12)
      M=$(tput setaf 13)
      C=$(tput setaf 14)
      W=$(tput setaf 15)
      END=$(tput sgr0)
      
      colorgcc()
          {
          perl -wln -M'Term::ANSIColor' -e '
          m/not found$/ and print "$ENV{N}$`$ENV{END}", "$&", "$ENV{END}"
          or
          m/found$/ and print "$ENV{N}$`${g}", "$&", "$ENV{END}"
          or
          m/yes$/ and print "$ENV{N}$`${g}", "$&", "$ENV{END}"
          or
          m/no$/ and print "$ENV{N}$`$ENV{END}", "$&", "$ENV{END}"
          or
          m/undefined reference to/i and print "$ENV{r}", "$_", "$ENV{END}"
          or
          m/ Error |error:/i and print "$ENV{r}", "$_", "$ENV{END}"
          or
          m/ Warning |warning:/i and print "$ENV{y}", "$_", "$ENV{END}"
          or
          m/nsinstall / and print "$ENV{c}", "$_", "$ENV{END}"
          or
          m/Linking |\.a\b/ and print "$ENV{C}", "$_", "$ENV{END}"
          or
          m/Building|gcc|g\+\+|\bCC\b|\bcc\b/ and print "$ENV{N}", "$_", "$ENV{END}"
          or
          print; '
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-10
        • 2023-04-09
        • 2019-07-09
        • 1970-01-01
        • 2016-08-28
        相关资源
        最近更新 更多