我在一些配置文件中有以下几行文本,需要使用Perl解析该文件,找到File:
行并使用一些正则表达式替换其内容以添加一些文本等。
File: logs/${byYearMonth}.log
我遇到的问题是正则表达式,因为我想在其中使用${byYearMonth}.log
,因为它易于阅读,可以轻松引用等等。但这看起来像Perl的变量插值而我得到以下简化的reg exp的以下编译错误:
... =~ s/...\Q${byYearMonth}.log\E.../.../m;
Global symbol "$byYearMonth" requires explicit package name (did you forget to declare "my $byYearMonth"?)
当然我可以重新编写reg exp,不要让Perl认为它是一个变量名,但上面提供的版本是我认为最容易阅读和搜索的版本。在思考和研究这个问题时,我没有找到任何解决办法,只允许我按原样保存reg exp并通过只添加一些标志或其他任何东西来防止Perl编译错误。
那么,是否有任何(简单)方法告诉Perl一些简单且已经引用的文本不会被插值以摆脱编译错误?
我觉得我错过了一些非常简单的东西,所以感谢您的提示! : - )
答案 0 :(得分:2)
\Q
和\E
用于引用正则表达式元字符。它们与变量插值无关。
如果使用带有单引号qr''
的{{1}}构建模式,Perl将不会插入变量。
''
输出:
use feature 'say';
my $foo = 1;
my $bar = qr/$foo/;
say $bar;
但是(?^:1)
:
qr''
输出:
my $foo = 1;
my $bar = qr'$foo';
say $bar;
答案 1 :(得分:1)
我打算将其他答案称为错误,因为通过正则表达式操纵看起来很像XML的东西是一个坏主意。
如果它实际上不是XML,那么使用看起来像XML但不是XML的数据格式是更糟糕的想法。
所以答案是“使用解析器”(或者,使用XML规范的累计副本生成文件的任何人)。
这样的内容会改变<File>
元素的内容:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $xml = XML::Twig -> new -> parsefile ( 'your_file.xml');
my $file_elt = $xml -> get_xpath ('//File',0);
print "Original value:", $file_elt -> text,"\n";
$file_elt -> set_text('some/other/path/${byWeek}.log');
$xml -> set_pretty_print ( 'indented' );
$xml -> print;
注意 - get_xpath
仅在树中的任何位置找到<File>
的第一个实例。如果您需要更具体,可以迭代或向xpath
添加其他限定符。
例如:
my $target_text = quotemeta '${byYearMonth}';
my $search_regex = qr/$target_text/;
foreach my $file_elt ( $xml -> get_xpath('//File') ) {
if ( $file_elt -> text =~ /$search_regex/ ) {
## set it to something else.
}
}
答案 2 :(得分:-3)
使用 quotemeta 转义模式,然后编译正则表达式。像这样的东西,它有效...
my $s = q[<timestamp key="byYearMonth" datePattern="yyyy-MM" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<File>logs/${byYearMonth}.log</File>
<Append>true</Append>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%date %-5level %logger.%M: %msg%n</Pattern>
</encoder>
</appender>];
my $pat = quotemeta('${byYearMonth}.log');
my $re = qr[$pat];
$s =~ s/$re/pop/g;
print $s;