如何在Perl正则表达式中转换看起来像变量插值的纯文本?

问题描述 投票:0回答:3

我在一些配置文件中有以下几行文本,需要使用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一些普通的和已经引用过的文本不会被插值以摆脱编译错误?

我有一种感觉,我错过了一些非常简单的东西,所以感谢您的提示! :-)

regex perl
3个回答
2
投票

\Q\E用于引用正则表达式元字符。它们与变量插值无关。

如果使用带单引号qr''''构造模式,Perl将不会插入变量。

use feature 'say';

my $foo = 1;
my $bar = qr/$foo/;
say $bar;

输出:

(?^:1)

但是使用qr''

my $foo = 1;
my $bar = qr'$foo';
say $bar;

输出:

(?^:$foo)

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. 
  }
}

-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;
© www.soinside.com 2019 - 2024. All rights reserved.