Regex 用perl脚本替换特定文本的重复

Regex 用perl脚本替换特定文本的重复,regex,perl,text,replace,Regex,Perl,Text,Replace,我有一个简单的perl脚本,它可以按照以下行进行大量文本替换: #!/usr/bin/perl { open(my $in, "<", "Texts.txt") or die "No input: $!"; open(my $out, ">", "TeXed/Texts.tex") or die "No output directory: $!"; LINE: while (<$in>) { s/(txt@)(.*)(?<!\t|\[)\[(.*)/\1\

我有一个简单的perl脚本,它可以按照以下行进行大量文本替换:

#!/usr/bin/perl
{
open(my $in, "<", "Texts.txt") or die "No input: $!";
open(my $out, ">",  "TeXed/Texts.tex") or die "No output directory: $!";
LINE: while (<$in>) {
    s/(txt@)(.*)(?<!\t|\[)\[(.*)/\1\2\\ovl{}\3/g;# 
    # there are a bunch of other replacements like the above
    print $out $_ ; 
    }
}
#/usr/bin/perl
{
打开(my$in,“,”TeXed/texs.tex“)或关闭“无输出目录:$!”;
行:while(){
s/(txt@)(*)(?)?
到目前为止还不错。我正在运行此脚本的文本被组织成块(长度不总是相同)。每个块都以相同的标识符(txt@)开头,然后是一个唯一的标签。每个标签都以一个#开头。
我希望实现的是删除所有重复的标签–基本上我只想保留标签的每个第一个实例,并替换/删除所有后续实例,直到标签更改。在下面的示例中,要替换/删除的标签以粗体显示

txt@#标签1一些文本
更多文本
更多的文字

txt@#标签1其他一些文本
更多文本
更多文本
更多的文字

txt@#标签1一些随机文本
更多文本
更多的文字

txt@#标签2一些文本
更多文本
更多文本
更多的文字

txt@#标签1一些文本
更多文本
更多的文字

txt@#标签3一些文本
更多文本
更多的文字

txt@#标签3一些文本
更多文本
更多的文字

txt@#标签1一些文本
更多文本
更多的文字

等等

很抱歉举了这么长的例子,我想不出更好的解释方法了

所以我想删除所有重复的Label1、Label2等,但不修改同一行以及后续行上的其余文本(一些文本,更多文本)。后续行的数量并不总是相同的(因此不是每n行都需要替换)


这在perl中是可能的吗?或者其他任何方式?(我没有嫁给perl,如果用另一种语言更容易的话,我很乐意尝试一下——我不是一个程序员,尽管非常感谢如此详细的说明).

引入“当前标签”——最新拾取的标签——并对其进行跟踪。一旦出现带有标签的行,比较:如果是相同的,则重复,因此删除它,否则替换它,我们将得到新的“当前”标签

处理是逐行进行的。或者,可以一次读取整个块以启用逐块处理,这可能更方便。代码显示在末尾

use warnings;
use strict;

open my $fh_out, '>', 'new_text_label.txt';
open my $fh_in, '<', 'text_label.txt';

# Our current (running) label
my $curr_label = '';

while (<$fh_in>)  
{
    # If line with label fetch it otherwise (print and) skip
    my ($label) = $_ =~ m/txt@#(\w+)/;
    if (not $label) {
        # ... process non-label line as needed ...
        print $fh_out $_;
        next;
    }       
    # Delete if repeated (matching the current), reset if new
    if ($curr_label eq $label) {
        s/(txt@)(?:#\w+)(.*)/$1$2/;
    }   
    else {
        $curr_label = $label;
    }   
    # ... process label-line as needed ...
    print $fh_out $_;
}

你想保留文本吗?你想如何对输出进行ogranize?是的,文本的其余部分必须保留(我刚刚编辑了文章以使其更清晰)。输出应保持其组织方式,我对文本执行了许多其他替换操作,但没有删除任何行。好的。因此,具有重复标签的行实际上会丢失标签,其他所有内容都保持不变?它确实有效!!!太好了,非常感谢您提供的提示解决方案!-还有一件事:我很高兴I’我也想去掉标签(标签的一部分)。修复了。因为没有任何东西依赖于正则表达式(除了删除),所以只需将
#
移动到非捕获组中即可。然后替换者不会将其放回。如果出现更多问题,请告诉我。是的,它现在可以工作了(我可能复制了错误的内容).还有一个问题:我应该把剩下的正则表达式放在哪里(在标签更换后处理)?我试图把
行放在
print
命令之前,但它给了我一个错误。好的,不用担心,我会处理它。这并不紧急。我现在已经把
s/
模式放在循环中了(在打印之前)但在替换中使用未初始化值$uuu(s//)
错误?@jan更改并重新排列了代码。现在它以一个逐行处理的版本开始。您应该能够将您的正则表达式(以及您拥有的任何其他处理)复制到显示“处理…”的位置。它仍然为您提供两个选项:标签行和非标签行的区分位置。然后,它显示了如果您希望执行每个块处理(这是原始帖子),将对代码进行哪些更改。都经过了测试。请告诉我它是如何运行的。@jan您遇到的错误是因为您的正则表达式使用了默认的
$\uu
,而我有一个命名变量
$bl
。我也改变了这一点,以便您可以简单地复制代码。原则上,我建议您使用正确命名的变量,特别是在复杂情况下处理经常调用
$\uuu
的代码。这样代码通常更清晰。太好了,非常感谢!第一个和第二个版本工作得很好。我使用第二个解决方案,因为其他替换同时搜索标签行和无标签行。在第一个版本中,我测试了将这些其他替换放在块w之前的开始处ith标签启动了,它也起了作用。什么时候一个标签会比另一个更好?(尽管将$改为$bl,但我没有让块处理工作正常,但我对我得到的很满意!)
while (<$fh_in>) 
{
     # If this is the label line, process it: delete or replace the label
     if (my ($label) = $_ =~ m/txt@#(\w+)/) {
        # Delete if repeated (matching the current), reset if new
        if ($curr_label eq $label) {
            s/(txt@)(?:#\w+)(.*)/$1$2/;
        }   
        else {
            $curr_label = $label;
        }
     }
     # The label is now fixed as needed. Process lines normally ...
     print $fh_out $_;
}
my @blocks = do { 
    # Set record separator to empty line to read blocks
    local $/ = "\n\n";
    open my $fh_in, '<', 'text_label.txt';
    <$fh_in>;    
};

# Our current (running) label
my $curr_label = '';

foreach my $bl (@blocks) 
{
     # The label pre-processing is exactly the same as above
     # Other processing can now utilize having the whole block in $bl
}