在我的Perl腳本中,我得到可能包含環境變量的文件路徑字符串,例如$FONTS/test.ttf
或$TMP/file.txt
。如何評估字符串中的shell變量?
我現在想打開這些文件是這樣的:
open my $handle, "<$filename" or die $!;
我現在如何才能擴大之前公開徵集的環境變量,例如作爲bash shell會做什麼?
在我的Perl腳本中,我得到可能包含環境變量的文件路徑字符串,例如$FONTS/test.ttf
或$TMP/file.txt
。如何評估字符串中的shell變量?
我現在想打開這些文件是這樣的:
open my $handle, "<$filename" or die $!;
我現在如何才能擴大之前公開徵集的環境變量,例如作爲bash shell會做什麼?
如果環境變量的設置,你可以使用一個簡單的替換:
$filename =~ s/\$(\w+)/$ENV{$1}/g;
整潔而簡潔 - 錯誤處理一如既往地將它搞砸。具體來說,如果沒有設置引用的環境變量之一,那麼您至多會得到意外的路徑;您也可能會收到有關從Perl訪問未定義變量的警告。雖然還有其他shell標記(如'$ {TMP}'),但它們很少用於那些會成爲問題的上下文中。 – 2010-08-16 14:14:24
@Jonathan,bash的標準行爲是將空字符串替換爲一個缺失的變量,所以這段代碼確實以OP所要求的方式處理了這個錯誤條件。我同意在腳本中使用'$ {FOO:?}'的備用shell符號來強制bash在未設置的變量上拋出錯誤。 – 2010-08-16 21:48:51
好以下是相當冗長,但它似乎 正確處理兩者$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--- ====== >
$
在這個版本中,未定義的符號與空字符串, 像殼更換。但在我的應用程序中,我寧願將未展開的 無效符號留在原地,以便更容易查看出了什麼問題。 另外,如果你搞砸你的支架匹配,外殼將 給你一個「錯誤的替代」的錯誤,但在這裏,我們只會返回 字符串與破碎的符號仍然在位。
抱歉,但你錯了。
在與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; '
}
爲什麼不只是這樣做:
$filename =~ s/\$\{(\w+)\}/$ENV{$1}/g;
$filename =~ s/\$(\w+)/$ENV{$1}/g;
你真的想在這裏打開3 arg來防止安全漏洞。 – xenoterracide 2010-08-16 14:22:40
不妨提供鏈接: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