2010-08-15 208 views
0

一些我們在Unix的使用情況如下(只是一個例子)的環境變量:Perl和環境變量

VAR1=variable1 
VAR2=variable2 
VAR3=variable3 
# and so on 

現在,我有一個Perl腳本(我們稱之爲test.pl)其內容界定的標籤文本文件(我們稱之爲test.txt),並將其中的內容逐列推入單獨的數組中。第一列test.txt包含以下信息(例如第一列中的字符串由/分隔,但我不知道如何可能/一個字符串將包含環境變量將出現在什麼位置):

$VAR1/$VAR2/$VAR3 
$VAR3/some_string/SOME_OTHER_STRING/and_so_on/$VAR2 
$VAR2/$VAR1/some_string/some_string_2/some_string_3/some_string_n/$VAR2 

腳本的提取物如下:

use strict; 
my $input0 = shift or die "must provide test.txt as the argument 0\n"; 
open(IN0,"<",$input0) || die "Cannot open $input0 for reading: $!"; 
my @first_column; 
while (<IN0>) 
{ 
    chomp; 
    my @cols = split(/\t/); 
    my $first_col = `eval $cols[0]`; #### but this does not work 
    # here goes the push stmt to populate the array 
    ### more code here 
} 
close(IN0); 

問:我如何可以訪問的環境變量,在這種情況下,使填充該數組如下:

$first_column[0] = variable1/vraible2/variable3 
$first_column[1] = variable3/some_string/SOME_OTHER_STRING/and_so_on/variable2 
$first_column[2] = variable2/variable1/some_string/some_string_2/some_string_3/some_string_n/variable2 
+1

你的問題是沒有意義的,請澄清..... – ennuikiller 2010-08-15 14:00:35

+0

我已經展示樣本輸入和我已經顯示了所需的結果。我還應該添加什麼? – sachin 2010-08-15 14:02:09

+0

你是否也允許像$ {VAR1:-foo}這樣的單詞的正常shell擴展或像$ {VAR1 // foo/bar}這樣的複雜擴展(即bashisms)? – 2010-08-15 14:09:34

回答

4

我認爲你正在尋找一種方法來處理配置文件。我喜歡Config::Std,雖然在CPAN上還有很多其他的。


這裏是處理的方式只是$cols[0]內容以明確的方式,你需要用它做什麼顯示:

#!/usr/bin/perl 

use strict; use warnings; 

# You should not type this. I am assuming the 
# environment variables are defined in the environment. 
# They are here for testing. 
@ENV{qw(VAR1 VAR2 VAR3)} = qw(variable1 variable2 variable3); 

while (my $line = <DATA>) { 
    last unless $line =~ /\S/; 
    chomp $line; 
    my @components = split qr{/}, $line; 
    for my $c (@components) { 
     if (my ($var) = $c =~ m{^\$(\w+)\z}) { 
      if (exists $ENV{$var}) { 
       $c = $ENV{$var}; 
      } 
     } 
    } 
    print join('/', @components), "\n"; 
} 

__DATA__ 
$VAR1/$VAR2/$VAR3 
$VAR3/some_string/SOME_OTHER_STRING/and_so_on/$VAR2 
$VAR2/$VAR1/some_string/some_string_2/some_string_3/some_string_n/$VAR2 

取而代之的是split/join的,你可以使用s///%ENV中的對應值替換看起來像變量的模式。爲了說明,我在__DATA__部分放置了第二列,它應該代表路徑的描述,並將每一行都轉換爲hashref。請注意,我分解出來的實際替代到eval_path所以你可以嘗試的替代品而不與主迴路搞亂:

#!/usr/bin/perl 

use strict; use warnings; 

# You should not type this. I am assuming the 
# environment variables are defined in the environment. 
# They are here for testing. 
@ENV{qw(VAR1 VAR2 VAR3)} = qw(variable1 variable2 variable3); 

my @config; 
while (my $config = <DATA>) { 
    last unless $config =~ /\S/; 
    chomp $config; 
    my @cols = split /\t/, $config; 
    $cols[0] = eval_path($cols[0]); 
    push @config, { $cols[1] => $cols[0] }; 
} 

use YAML; 
print Dump \@config; 

sub eval_path { 
    my ($path) = @_; 
    $path =~ s{\$(\w+)}{ exists $ENV{$1} ? $ENV{$1} : $1 }ge; 
    return $path; 
} 

__DATA__ 
$VAR1/$VAR2/$VAR3 Home sweet home 
$VAR3/some_string/SOME_OTHER_STRING/and_so_on/$VAR2 Man oh man 
$VAR2/$VAR1/some_string/some_string_2/some_string_3/some_string_n/$VAR2 Can't think of any other witty remarks ;-) 

輸出:

--- 
- Home sweet home: variable1/variable2/variable3 
- Man oh man: variable3/some_string/SOME_OTHER_STRING/and_so_on/variable2 
- Can't think of any other witty remarks ;-): variable2/variable1/some_string/some_string_2/some_string_3/some_string_n/variable2
+1

我同意,只是使用配置模塊,而不是重新發明輪...恕我直言,初學者程序員和中級程序員之間的區別是中級程序員開始有心態*「有**沒有辦法**我的問題有以前從未有人遇到過......我打賭有一個圖書館已經爲我解決了這個問題。「*初學者只是拼命向前,以爲他們處於未知領域。 – Ether 2010-08-15 15:34:48

+0

謝謝思南。這非常有幫助 – sachin 2010-08-16 16:03:41

0

Perl保持其環境變量爲%ENV,在您的情況下,您可以像這樣更改代碼:

my $first_col = $ENV[$cols[0]]; 
+0

我認爲這是行不通的,因爲確切包含的$ cols [0]在%ENV中不可用。糾正我,如果我錯了。 – sachin 2010-08-15 14:00:55

+0

@sachin:是的,使用正則表達式可能會有更實用更優雅的解決方案,但請告訴我們'確切內容'是什麼。爲什麼他們不能在'%ENV'中使用? – MvanGeest 2010-08-15 14:02:54

+0

@MvanGeest'%ENV'將具有'$ ENV {VAR1}'等不是'$ ENV {$ VAR1/$ VAR2/$ VAR3}'。 – 2010-08-15 14:39:14

1

如果你想允許全shell擴展,一個選項使用shell爲您做擴展,或許通過echo:

 
$ cat input 
$FOO 
bar 
${FOO//cat/dog} 
$ FOO=cat perl -wpe '$_ = qx"echo $_"' input 
cat 
bar 
dog 

如果您不能相信環境變量的內容,則會引入安全風險,因爲對字符串調用qx可能會導致shell調用嵌入在字符串中的命令。因此,這個scriptlet不會在污染模式(-T)下運行。

1

我覺得你只是想這樣做:

my @cols = map { s/(\$(\w+))/ $ENV{$2} || $1 /ge; $_ } split /\t/; 

,你會怎麼做,這裏是你拆後他們,你會採取其次'$'每個序列字符,並檢查是否有看到一個環境變量的單詞部分,否則保持原樣。

  • e開啓替代功能後,您可以執行替換值的代碼。
  • 如果您希望'0'用於任何環境變量值,則最好使用定義的或使用5.10來定義的

    my @cols = map { s|(\$(\w+))| $ENV{$2} // $1 |ge; $_ } split /\t/; 
    

(忽略的標記。//是一個定義,或者,不C-評論)

+0

真的很酷,通過Regex完成它 – sachin 2010-08-16 16:12:55