gpt4 book ai didi

regex - 如何有效地处理同一字符串上的多个 Perl 搜索/替换操作?

转载 作者:行者123 更新时间:2023-12-04 16:30:37 24 4
gpt4 key购买 nike

所以我的 Perl 脚本基本上接受一个字符串,然后尝试通过对其进行多次搜索和替换来清理它,如下所示:

$text =~ s/<[^>]+>/ /g;
$text =~ s/\s+/ /g;
$text =~ s/[\(\{\[]\d+[\(\{\[]/ /g;
$text =~ s/\s+[<>]+\s+/\. /g;
$text =~ s/\s+/ /g;
$text =~ s/\.*\s*[\*|\#]+\s*([A-Z\"])/\. $1/g; # replace . **** Begin or . #### Begin or ) *The
$text =~ s/\.\s*\([^\)]*\) ([A-Z])/\. $1/g; # . (blah blah) S... => . S...

如您所见,我正在处理令人讨厌的 html,并且必须击败它才能提交。

我希望有一种更简单、更美观的方式来做到这一点。我有大约 50 行看起来就像上面的一样。

我已经通过使用哈希解决了这个问题的一个版本,其中键是注释,哈希是 reg 表达式,如下所示:
%rxcheck = (
'time of day'=>'\d+:\d+',
'starts with capital letters then a capital word'=>'^([A-Z]+\s)+[A-Z][a-z]',
'ends with a single capital letter'=>'\b[A-Z]\.'
}

这就是我使用它的方式:
 foreach my $key (keys %rxcheck) {
if($snippet =~ /$rxcheck{ $key }/g){ blah blah }
}

当我尝试一个哈希值时,问题就出现了,其中键是表达式,它指向我想要替换它的内容......并且里面有一个 $1 或 $2。
%rxcheck2 = (
'(\w) \"'=>'$1\"'
}

上面就是这样做的:
$snippet =~ s/(\w) \"/$1\"/g;

但我似乎无法将“$1”部分按字面意思传递到正则表达式中(我认为这是正确的词......即使我使用了 ' 标记,似乎 $1 正在被解释。)所以这导致:
if($snippet =~ /$key/$rxcheck2{ $key }/g){  }

那是行不通的。

所以2个问题:

简单:如何以易于编辑的方式处理大量正则表达式,以便我可以更改和添加它们,而无需剪切和粘贴之前的行?

更难:我如何使用散列(或数组,如果我想包含多个部分,例如 1)要搜索的部分,2)替换 3)注释,4)全局/不区分大小写的修饰符),如果这实际上是最简单的方法吗?

谢谢你的帮助 -

最佳答案

问题 #1

由于各个正则表达式似乎没有多少结构共享,因此没有比仅列出您所做的命令更简单或更清晰的方法。在这样的代码中减少重复的一种常见方法是移动 $text进入 $_ ,所以不必说:

$text =~ s/foo/bar/g;

你可以说:
s/foo/bar/g;

这样做的一个常见习惯用法是使用简并 for()循环作为主题器:
for($text)
{
s/foo/bar/g;
s/qux/meh/g;
...
}

此 block 的范围将保留 $_ 的任何预先存在的值,因此无需显式 local放大 $_ .

至此,您已经消除了几乎所有非样板字符——即使在理论上,它还能缩短多少?

除非你真正想要的(正如你的问题 #2 所暗示的)是改进的模块化,例如,迭代、报告、计数等所有正则表达式的能力。

问题 #2

您可以使用 qr//引用替换的“搜索”部分的语法:
my $search = qr/(<[^>]+>)/;
$str =~ s/$search/foo,$1,bar/;

但是我不知道如何充分引用“替换”部分。我曾希望 qr//也适用于此,但事实并非如此。有两种选择值得考虑:

1. 使用eval()在您的 foreach环形。 这将使您能够保留当前的 ​​ %rxcheck2哈希。缺点:您应该始终关注字符串 eval() 的安全性s。

2. 使用匿名子程序数组:
my @replacements = (
sub { $_[0] =~ s/<[^>]+>/ /g; },
sub { $_[0] =~ s/\s+/ /g; },
sub { $_[0] =~ s/[\(\{\[]\d+[\(\{\[]/ /g; },
sub { $_[0] =~ s/\s+[<>]+\s+/\. /g },
sub { $_[0] =~ s/\s+/ /g; },
sub { $_[0] =~ s/\.*\s*[\*|\#]+\s*([A-Z\"])/\. $1/g; },
sub { $_[0] =~ s/\.\s*\([^\)]*\) ([A-Z])/\. $1/g; }
);

# Assume your data is in $_
foreach my $repl (@replacements) {
&{$repl}($_);
}

您当然可以使用散列代替一些更有用的键作为散列,和/或您可以使用多值元素(或散列值),包括注释或其他信息。

关于regex - 如何有效地处理同一字符串上的多个 Perl 搜索/替换操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/843542/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com