2

我有一个名为“input.file”的文件,其中包含以下行:

Foo 是 $COLOR

$COLOR 被分配为“红色”,我正在尝试使用以下行创建名为“output.file”的第二个文件:

福是红色的

这是我失败的尝试:

#!/usr/bin/perl
use strict;
use warnings;

my $COLOR = "red";

open(FILE_IN, "< input.file");
open(FILE_OUT, "> output.file");

while (<FILE_IN>){

    # Prints 'Foo is $COLOR' to 'output.file'
    print FILE_OUT;
}

close FILE_IN;
close FILE_OUT;

# Prints 'Foo is red' to STDOUT
print "Foo is $COLOR\n";

那么在打印到“output.file”时如何打印“red”而不是“$COLOR”?

谢谢

4

1 回答 1

4

一个通用的解决方案

让我们假设一个字符串包含与正则表达式匹配的占位符/\$\w+/。我们还有一个哈希映射名称到值,例如:

my %replacements = (
  COLOUR => 'red',
  x => 42,
  perl_snippet => '$x++ == 3',
);

所以输入

my $input = <<'END';
My favourite colour is $COLOUR.
The meaning of life is $x. Here is some Perl: `$perl_snippet`
$undefined
END

应该转变为

My favourite colour is red.
The meaning of life is 42. Here is some Perl: `$x++ == 3`
$undefined

不是

My favourite colour is red.
The meaning of life is 42. Here is some Perl: `42++ == 3`

这可以通过匹配占位符、使用名称作为哈希键并仅在替换哈希中存在适当条目时进行替换来实现:

(my $output = $input) =~
   s/\$(\w+)/exists $replacements{$1} ? $replacements{$1} : '$'.$1/eg;

或者

(my $output = $input) =~
   s/\$(\w+)(?(?{exists $replacements{$1}})|(*F))/$replacements{$1}/g;

这种使用单次替换和散列的策略也保证了字符串的每个部分只被评估一次,并且不会发生双重插值。

具体解决方案

如果只需要插入一个占位符,我们可以通过不使用散列来简化:

s/\$COLOR/red/g;

这有以下缺点:

  • 您只能有一个这样的替代品。添加另一个s///使双重转义成为可能,这通常是一个错误。
  • 您无法在运行时轻松查询或修改替换值或占位符。
于 2013-06-04T22:54:42.010 回答