Perl one-liner扩展Unix环境变量

时间:2011-10-08 13:46:16

标签: perl unix

我有一个Perl脚本,可以完成扩展Unix环境变量的工作。脚本运行正常。脚本如下:

# I know this should not be typed here. This is here just for testing.
@ENV{qw(LKUP_DIR DATA_DIR CTRL_DIR MMM)} = qw(/appl1/TSS/lkup /appl1/TSS/data /appl1/TSS/ctrl Oct);
while ( <DATA> )
{
  my $line=$_;
  chomp $line;
  $line =~ s{\$(\w+)}{ exists $ENV{$1} ? $ENV{$1} : '$'.$1 }ge;
  $line =~ s{\$\{(\w+)\}}{ exists $ENV{$1} ? $ENV{$1} : '${'.$1.'}' }ge;
  print "$line\n";
}

__DATA__
${LKUP_DIR}/lookup_file.txt
${CTRL_DIR}/ctrl_file_$MMMM.txt
$CTRL_DIR/ctrl_file_$MMM.txt

我想将此脚本转换为单行,但我不确定如何处理上述脚本中使用的正则表达式中$周围的单引号。我尝试了以下,但当然它不起作用:

perl -lne '$line=$_; $line =~ s{\$(\w+)}{ exists $ENV{$1} ? $ENV{$1} : '$'.$1 }ge; $line =~ s{\$\{(\w+)\}}{ exists $ENV{$1} ? $ENV{$1} : '${'.$1.'}' }ge; print "$line";' DATA.txt

有什么建议吗? (我想只在Perl中这样做。)

2 个答案:

答案 0 :(得分:2)

我同意@Mat:这似乎是一个坏主意。这将只是一行,但你的可读性会下降。只是想想你可能会在一年之后进行编辑,并且仍然试着了解一个班轮的作用。

但无论如何,在Perl中,您可以使用q/STRING/代替'STRING'

perl -lne '$line=$_; $line =~ s{\$(\w+)}{ exists $ENV{$1} ? $ENV{$1} : q/$/.$1 }ge; $line =~ s{\$\{(\w+)\}}{ exists $ENV{$1} ? $ENV{$1} : q/${/.$1.q/}/ }ge; print "$line";' DATA.txt

答案 1 :(得分:2)

这是一个更简洁的脚本版本。一个显着的区别是我使用//而不是exists。我认为,环境变量所涉及的差异可以忽略不计。如果环境变量存在但未定义,那么它是什么?如果它确实是未定义的,那么在perl打印它时会引发警告。

perl -wpe 's#\${?(\w+)}?# $ENV{$1} // $& #ge;' DATA.txt

如果您仍然坚持使用exist,只需使用:

perl -wpe 's#\${?(\w+)}?# exists $ENV{$1} ? $ENV{$1} : $& #ge;' DATA.txt

我做了什么:

  • 删除了无用的转换变量$line
  • 已移除-l选项
  • -n
  • 交换print-p
  • 将替换上的分隔符更改为不必转义{}
  • 通过添加}?作为可选匹配
  • 来组合正则表达式
  • 使用$& - 完整匹配 - 而不是试图拼图部分 比赛重新组合