gpt4 book ai didi

regex - 如何将此 perl 单行代码转换为脚本(特别是多行、全局正则表达式替换)

转载 作者:行者123 更新时间:2023-12-01 08:26:49 25 4
gpt4 key购买 nike

我有一个包含多个 XML 标记的文件,如下所示:

<Good>Yay!</Good>
<Great>Yup!</Great>
<Bad>booo</Bad>
<Bad>
<Ok>not that great</ok>
</Bad>
<Good>Wheee!</Good>

我想去掉“坏”标签和介于两者之间的任何东西。所以它会变成:

<Good>Yay!</Good>
<Great>Yup!</Great>
<Good>Wheee!</Good>

我知道这个单行:

perl -pe "undef $/;s/<Bad>.*?<\/Bad>//msg" < originalFile > newlyStrippedFile

似乎 做我想做的一切(除了放入额外的换行符,但希望我能足够轻松地处理它)

但是我需要把它放在一个脚本中(两个文件被读入命令行,一个包含所有标签,另一个包含要提取的标签列表),所以同样的东西会被称为多个次。

我只是遇到了麻烦。要么它只读取一行,要么我出错,要么两者兼而有之。

这是我最新尝试的相关部分:

open ORIGINAL_FILE, $sdb_pathname
or die "Can't open '$sdb_pathname' : $!";

@sdb_input_array = <ORIGINAL_FILE>;

close ORIGINAL_FILE;
@sdb_input_scalar=join("",@sdb_input_array);

foreach $tag (@tags) {
&remove_tag($tag);
}

sub remove_tag
{
my($current_tag) = @_;

$sdb_input_scalar =~ s/<$current_tag>.*?<\/$current_tag>//msg;

open NEWLY_STRIPPED_FILE, $clean_sdb_pathname
or die "Can't open '$clean_sdb_pathname' : $!";

print(NEWLY_STRIPPED_FILE $sdb_input_scalar);
close(NEWLY_STRIPPED_FILE);

}

这让我“在我的 $sdb_input_scalar =~ 行中使用未初始化的值 $sdb_input_scalar 代替 (s///)。和仅为输入打开的文件句柄 NEWLY_STRIPPED_FILE

当然,我的两个文件看起来仍然一模一样,就好像我什么也没做一样。

如果我遗漏了一些明显的东西,我很抱歉,但我确实是 perl 的新手。工作人员估计需要 8 小时来完成此脚本,而我已经用了 5 个多小时来安装 perl、学习语法并使其他方面正常运行。我知道有一个 XML::Parser 模块,但我发现这些示例非常多,因为我只剩下很短的时间来完成。

我必须假设我的正则表达式是正确的,因为单行代码工作得很好。谁能帮我调整它以适应我的需要?

最佳答案

您真的应该使用 XML 解析器。这几乎可以保证 XML 文件不会按照您期望的正则表达式解析方式进行解析。但是,让我们先开始吧。

你在哪里:

@sdb_input_scalar=join("",@sdb_input_array);

你实际上想要:

$sdb_input_scalar=join("",@sdb_input_array);

现在一些其他提示。

在脚本的顶部确保使用 -w 标志启用警告,如下所示:

#!/path/to/perl -w

use strict;

一旦您添加了 use strict ,它会导致您出现一些错误,但这是一件好事。我们将实现一些范围和其他良好做法。您现在需要用 my 初始化变量(以 $、@ 或 % 开头)。例如:

my @sdb_input_array = <ORIGINAL_FILE>;

或:

foreach my $tag (@tags) { ... }

不要像现在这样调用 open,而是使用三个论证版本:

open ($originalFile, "<", $sdb_pathname)
or die "Can't open '$sdb_pathname' : $!";

my @sdb_input_array = <$originalFile>;

这会将其设置为只读。参见 http://perldoc.perl.org/functions/open.html

通常你应该避免依赖全局变量。更改调用 remove_tag() 的方式:

foreach $tag (@tags) {
$sdb_input_scalar = remove_tag($sdb_input_scalar, $tag);
}

要支持这一点,您还需要更改函数:

sub remove_tag 
{
my($input, $current_tag) = @_;

$input =~ s/<$current_tag>.*?<\/$current_tag>//msg;

return $input;
}

在迭代所有标签后,您可以通过将其移到 remove_tag 函数之外来写一次:

   open ($strippedFile, ">", $clean_sdb_pathname)
or die "Can't open '$clean_sdb_pathname' : $!";

print $strippedFile $sdb_input_scalar;
close($strippedFile);

关于regex - 如何将此 perl 单行代码转换为脚本(特别是多行、全局正则表达式替换),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13929665/

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