我正在操作文本文件,并且需要构建一个perl脚本来运行搜索替换仅在给定文本部分的注释(本例中的章节),以便我可以转换此模式:
Chapter 1:1 text here(Note a) more text here(Note b)
2 text here(Note c) more text here(Note d)
3 text here(Note e) more text here(Note f)
4 text here(Note g) more text here(Note h)
Chapter 2:1 text here(Note i) more text here(Note j)
2 text here(Note k) more text here(Note l)
3 text here(Note m) more text here(Note n)
4 text here(Note o) more text here(Note p)
5 text here(Note q) more text here(Note r)
6 text here(Note s) more text here(Note t)
进入这个:
Chapter 1:1 text here(Note a) more text here(Note b)
2 text here(Note c) more text here(Note d)
3 text here(Note e) more text here(Note f)
4 text here(Note g) more text here(Note h)
Chapter 2:1 text here(Note a) more text here(Note b)
2 text here(Note c) more text here(Note d)
3 text here(Note e) more text here(Note f)
4 text here(Note g) more text here(Note h)
5 text here(Note i) more text here(Note j)
6 text here(Note k) more text here(Note l)
换句话说,我需要在每个新章的开头将每个音符的“计数器”设置为“a”。以下正则表达式匹配每一章:
(?s)^\w{1,10} \d{1,3}:\d{1,3}.+?\(Note \w\).+?(?=\w{1,10} \d{1,3}:\d{1,3})
我尝试使用像这样的while循环:
my @notes = ('Note a', 'Note b', 'Note c', 'Note d');
$Count = a;
foreach my $Marker (@notes) {
$_=~s/(\\(Note\\))[a-z]/"$1".$Count++/e;
}
但我陷入困境,不可能想到一种方法来构建一个脚本,使其在每个章节中停止,然后再次开始直到结束。也许我使用了错误的方法?
如上所示(即第一个正则表达式),我需要做什么才能应用搜索并仅替换每个章节?
任何帮助将不胜感激。 谢谢!
编辑(7月30日)
两个答案都很好。我把第一个投票作为我的最爱,因为我更了解逻辑,但两者同样有效。
现在,作为我第一个问题的必然结果。如何在每行之前轻松地包含章节名称和章节编号顺序?像这样:
Chapter 1:1 text here(Note a) more text here(Note b)
Chapter 1:2 text here(Note c) more text here(Note d)
Chapter 1:3 text here(Note e) more text here(Note f)
Chapter 1:4 text here(Note g) more text here(Note h)
Chapter 2:1 text here(Note a) more text here(Note b)
Chapter 2:2 text here(Note c) more text here(Note d)
Chapter 2:3 text here(Note e) more text here(Note f)
Chapter 2:4 text here(Note g) more text here(Note h)
Chapter 2:5 text here(Note i) more text here(Note j)
Chapter 2:6 text here(Note k) more text here(Note l)
我是否需要使用变量并递增它或者是否有更简单的方法?
答案 0 :(得分:3)
您应该将文本拆分为章节并单独处理。
# $book holds your text
my @chapters = split /^(?=Chapter\s+\d+:\d+)/m, $book;
for my $chap (@chapters) {
my $cnt = 'a';
$chap =~ s/(?<=\(Note )[a-z]/$cnt++/ge;
print $chap;
}
这适用于您的示例。你只需要弄清楚如何处理超过26个音符(a-z)。
编辑:这是你可以逐行阅读文本并编写输出文件的方法:
open IN, 'infile.txt';
open OUT, '>', 'outfile.txt';
my $cnt;
for my $line (<IN>) {
$cnt = 'a' if $line =~ /^Chapter\s+\d+:\d+/;
$line =~ s/(?<=\(Note )[a-z]/$cnt++/ge;
print OUT $line;
}
答案 1 :(得分:0)
你也可以不分裂,如下所示:
s/^(chapter\s+\d+:\d+)|(\(note\s+)[a-z]+(?=\))/$a='a'if$1; $1?$1:$2.$a++/gime;
PS:不要忘记use strict;
和use warnings;
。
基于OP评论的完整示例:
use strict;
use warnings;
open my $fh, '<', '/Users/rgp/Desktop/Test.txt' or die "cant open file: $!";
my $content = do { local $/ = undef; <$fh> };
close $fh;
$content =~ s/^(chapter\s+\d+:\d+)|(\(note\s+)[a-z]+(?=\))/$a='a'if$1; $1?$1:$2.$a++/gime;
print "Result:\n";
print $content;