我需要您的专业帮助才能使用perl修复此正则表达式代码?
我有这个数据文件......
__Data__ SCSI - test-A ccccccccccccccccc aaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb __Data__ SCSI - test-B ccccccccccccccccc aaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb __Data__ SCSI - test-C ccccccccccccccccc aaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb
我想要以下输出
__Data__ SCSI - test-A __Data__ SCSI - test-B __Data__ SCSI - test-C
相反,我得到的输出缺少两个数据记录的__Data__
。
__Data__ SCSI - test-A SCSI - test-B SCSI - test-C
这里的代码..
$/ = "__Data__"; # setting the input separator variable to __Data__
while(<ReadFile>)
{
$_ =~ s/(SCSI.*test-(A|B|C)?)(.*)/$1/ms;
print $_;
}
答案 0 :(得分:2)
你告诉Perl这些行以__DATA__
结束,所以你得到了
1: "__Data__"
2: "\nSCSI - test-A\nccc\naaa\nbbb\n\n__Data__"
3: "\nSCSI - test-B\nccc\naaa\nbbb\n\n__Data__"
4: "\nSCSI - test-C\nccc\naaa\nbbb\n"
但你错误地认为你得到了
1: "__Data__\nSCSI - test-A\nccc\naaa\nbbb\n\n"
2: "__Data__\nSCSI - test-B\nccc\naaa\nbbb\n\n"
3: "__Data__\nSCSI - test-C\nccc\naaa\nbbb\n"
解决方案:
my $after_data = 0;
while (<>) {
if (/^__Data__$/) {
print;
$after_data = 1;
}
elsif ($after_data) {
print;
print "\n";
$after_data = 0;
}
}
您还可以使用段落模式:
local $/ = '';
while (<>) {
print /^(.*\n.*\n)/;
print "\n";
}
答案 1 :(得分:0)
尝试添加
$\ = $/;
...也设置输出记录分隔符。
但是,你最终会以__Data__
这样的最终虚假实例结束,因为它在每条记录之后打印(在每个print
的末尾)。
或者,您可以自己拆分输入:
while (<ReadFile>)
{ chomp;
next unless $_ eq '__Data__'; print;
my $next = <ReadFile>;
$next =~ s/(SCSI.*text-(A|B|C)?).*/$1/ms;
print $next;
}
答案 2 :(得分:0)
将输入记录分隔符设置为空字符串以启用段落模式。在打印中添加换行符。
$/ = ""; # paragraph mode
while (<ReadFile>) {
$_ =~ s/(SCSI.*test-(A|B|C))(.*)/$1/s;
print "$_\n\n";
}
答案 3 :(得分:0)
您似乎想要打印适合三个类别之一的行。
__Data__
标记 Perl的段落模式在它工作时很方便,但它很脆弱。段落由完全序列"\n\n"
终止,但是当段落后面有一个空白但非空行时,不显示空格的编辑器会使调试变得棘手。
如您的问题中所述,下面的代码会生成您想要的输出。
#! /usr/bin/env perl
use strict;
use warnings;
use 5.10.0; # smart matching
*ARGV = *DATA; # for demo only
my @interesting_line = (qr/^__Data__/, qr/SCSI - test-/, qr/^\s*$/);
while (<>) {
print if $_ ~~ @interesting_line;
print "\n" if eof && !eof();
}
__DATA__
__Data__
SCSI - test-A
ccccccccccccccccc
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb
__Data__
SCSI - test-B
ccccccccccccccccc
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb
__Data__
SCSI - test-C
ccccccccccccccccc
aaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbb
在实际使用中,您将删除标记为仅演示的行,然后在命令行上提供一个或多个数据文件。看起来很滑稽的if eof && !eof()
测试试图确定何时在记录之间插入额外的分隔符。如果你想要它完全正确,你需要更加慎重。
以下是多个文件的输入示例。
$ cat input1 __Data__ SCSI - test-A ccccccccccccccccc aaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb __Data__ SCSI - test-B ccccccccccccccccc aaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb $ cat input2 __Data__ SCSI - test-C ccccccccccccccccc aaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbb $ ./extract-tests input1 input2 __Data__ SCSI - test-A __Data__ SCSI - test-B __Data__ SCSI - test-C