2010-08-16 69 views
6

在我的Perl腳本中,我得到可能包含環境變量的文件路徑字符串,例如$FONTS/test.ttf$TMP/file.txt如何評估字符串中的shell變量?

我現在想打開這些文件是這樣的:

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

我現在如何才能擴大之前公開徵集的環境變量,例如作爲bash shell會做什麼?

+5

你真的想在這裏打開3 arg來防止安全漏洞。 – xenoterracide 2010-08-16 14:22:40

+1

不妨提供鏈接:http://stackoverflow.com/questions/318789/whats-the-best-way-to-open-and-read-a-file-in-perl http://stackoverflow.com/問題/ 1479741/why-is-three-argument-open-calls-with-lexical-filehandles-a-perl-best-practice – daxim 2010-08-16 14:44:26

回答

12

如果環境變量的設置,你可以使用一個簡單的替換:

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

整潔而簡潔 - 錯誤處理一如既往地將它搞砸。具體來說,如果沒有設置引用的環境變量之一,那麼您至多會得到意外的路徑;您也可能會收到有關從Perl訪問未定義變量的警告。雖然還有其他shell標記(如'$ {TMP}'),但它們很少用於那些會成爲問題的上下文中。 – 2010-08-16 14:14:24

+0

@Jonathan,bash的標準行爲是將空字符串替換爲一個缺失的變量,所以這段代碼確實以OP所要求的方式處理了這個錯誤條件。我同意在腳本中使用'$ {FOO:?}'的備用shell符號來強制bash在未設置的變量上拋出錯誤。 – 2010-08-16 21:48:51

0

好以下是相當冗長,但它似乎 正確處理兩者$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--- ====== > 
$ 

在這個版本中,未定義的符號與空字符串, 像殼更換。但在我的應用程序中,我寧願將未展開的 無效符號留在原地,以便更容易查看出了什麼問題。 另外,如果你搞砸你的支架匹配,外殼將 給你一個「錯誤的替代」的錯誤,但在這裏,我們只會返回 字符串與破碎的符號仍然在位。

0

抱歉,但你錯了。

在與shell變量perl的工作,正確的語法是:$ ENV {變量}

例如用彩色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; ' 
    } 
2

爲什麼不只是這樣做:

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