2010-08-15 213 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