如何在阅读Perl时跳过某些块内容
我计划跳过块内容,其中包括“MaterializeU4()”的起始行以及下面的子例程()如何在阅读Perl时跳过某些块内容,perl,expression,Perl,Expression,我计划跳过块内容,其中包括“MaterializeU4()”的起始行以及下面的子例程()read\u block。但失败了 # Read a constant definition block from a file handle. # void return when there is no data left in the file. # Otherwise return an array ref containing lines to in the block. sub read_
read\u block
。但失败了
# Read a constant definition block from a file handle.
# void return when there is no data left in the file.
# Otherwise return an array ref containing lines to in the block.
sub read_block {
my $fh = shift;
my @lines;
my $block_started = 0;
while( my $line = <$fh> ) {
# how to correct my code below? I don't need the 2nd block content.
$block_started++ if ( ($line =~ /^(status)/) && (index($line, "MaterializeU4") != 0) ) ;
if( $block_started ) {
last if $line =~ /^\s*$/;
push @lines, $line;
}
}
return \@lines if @lines;
return;
}
#从文件句柄读取常量定义块。
#当文件中没有剩余数据时,返回void。
#否则,返回一个数组ref,该数组ref包含块中的行。
子读取块{
我的$fh=班次;
我的@行;
我的$block_start=0;
而(我的$line=){
#如何更正下面的代码?我不需要第二块内容。
$block_started++if($line=~/^(status)/)&&&(index($line,“MaterializeU4”)!=0);
如果($block_启动){
最后一个if$line=~/^\s*$/;
按@行,$line;
}
}
如果@行,则返回\@行;
返回;
}
数据如下:
__DATA__
status DynTest = <dynamic 100>
vid = 10002
name = "DynTest"
units = ""
status VIDNAME9000 = <U4 MaterializeU4()>
vid = 9000
name = "VIDNAME9000"
units = "degC"
status DynTest = <U1 100>
vid = 100
name = "Hello"
units = ""
数据
状态动态测试=
vid=10002
name=“DynTest”
units=“”
状态VIDNAME9000=
vid=9000
name=“VIDNAME9000”
单位=“degC”
状态动态测试=
vid=100
name=“你好”
units=“”
输出:
<StatusVariables>
<SVID logicalName="DynTest" type="L" value="100" vid="10002" name="DynTest" units=""></SVID>
<SVID logicalName="DynTest" type="L" value="100" vid="100" name="Hello" units=""></SVID>
</StatusVariables>
[更新]
我打印索引($line,“MaterializeU4”)
的值,它输出25
。
然后我更新了代码如下
$block_start++if($line=~/^(status)/)和&(index($line,“materialieu4”)!=25)
现在它起作用了
欢迎对我的做法提出任何意见。成功匹配子字符串时,返回子字符串的位置,可以是任何值>=0。在“失败”时,
索引
返回-1
您使用索引的方式
index($line, "MaterializeU4") != 0
对于除以字符串“MaterializeU4”
开头的行以外的所有行都将为true
看起来您对Perl正则表达式已经了解了一点,为什么不在本例中也使用一个呢
++$block_started if $line =~ /status/ && $line =~ /MaterializeU4/;
我看到的另一个问题是,您将
$block\u start
设置为开始捕获行,但从未在“block”末尾将其设置为零,例如,$line
为空。我不确定这是否是您想要做的。成功匹配子字符串时,返回子字符串的位置,可以是任何值>=0。在“失败”时,索引
返回-1
您使用索引的方式
index($line, "MaterializeU4") != 0
对于除以字符串“MaterializeU4”
开头的行以外的所有行都将为true
看起来您对Perl正则表达式已经了解了一点,为什么不在本例中也使用一个呢
++$block_started if $line =~ /status/ && $line =~ /MaterializeU4/;
我看到的另一个问题是,您将
$block\u start
设置为开始捕获行,但从未在“block”末尾将其设置为零,例如,$line
为空。我不确定这是否是您想要做的。首先,使用正则表达式而不是索引可能更好,因为如果您决定更严格,而不仅仅是“substring exists”,您可以将其调整为状态字符串的精确格式
我建议作为一种解决方案,添加第二个标志以跳过块内容(如果是MaterializeU4块),如下所示:
# Read a constant definition block from a file handle.
# void return when there is no data left in the file.
# Empty return for skippable (Materialize4U) block!!!
# Otherwise return an array ref containing lines to in the block.
sub read_block {
my $fh = shift;
my @lines = ();
my $block_started = 0;
my $block_ignore = 0;
while (my $line = <$fh> ) {
if ($line =~ /^status.*?((MaterializeU4)?)/) {
$block_started = 1;
$block_ignore = 1 if $1;
}
last if $line =~ /^\s*$/ && $block_started;
push @lines, $line unless $block_ignore;
}
return \@lines if @lines || $block_started;
return;
}
输出:
$VAR1 = [
's 1',
'b 1'
];
$VAR1 = [];
$VAR1 = [
's 3',
'b 3'
];
首先,使用正则表达式而不是索引可能更好,因为如果您决定比“substring exists”更严格,您可以将其调整为状态字符串的精确格式 我建议作为一种解决方案,添加第二个标志以跳过块内容(如果是MaterializeU4块),如下所示:
# Read a constant definition block from a file handle.
# void return when there is no data left in the file.
# Empty return for skippable (Materialize4U) block!!!
# Otherwise return an array ref containing lines to in the block.
sub read_block {
my $fh = shift;
my @lines = ();
my $block_started = 0;
my $block_ignore = 0;
while (my $line = <$fh> ) {
if ($line =~ /^status.*?((MaterializeU4)?)/) {
$block_started = 1;
$block_ignore = 1 if $1;
}
last if $line =~ /^\s*$/ && $block_started;
push @lines, $line unless $block_ignore;
}
return \@lines if @lines || $block_started;
return;
}
输出:
$VAR1 = [
's 1',
'b 1'
];
$VAR1 = [];
$VAR1 = [
's 3',
'b 3'
];
Perl已经有了一个跟踪块的操作符。它被称为“触发器”操作符: 试试这个:
while ( <DATA> ) {
next if /\Q<U4 MaterializeU4()>\E/../^\s*$/;
push @lines, $_;
}
while(){
下一个if/\Q\E/./^\s*$/;
按@行,$\;
}
当看到与起始正则表达式匹配的行时,
/\Q\E/./^\s*$/
的值将为真,当它看到与第二个表达式匹配的行时,它将停止为真。Perl已经有一个跟踪块的运算符。它被称为“触发器”运算符:
试试这个:
while ( <DATA> ) {
next if /\Q<U4 MaterializeU4()>\E/../^\s*$/;
push @lines, $_;
}
while(){
下一个if/\Q\E/./^\s*$/;
按@行,$\;
}
/\Q\E/./^\s*$/
的值在看到与起始正则表达式匹配的行时将为真,在看到与第二个表达式匹配的行后将不再为真。规则。实际上,daotoad很乐意将完整的示例代码作为另一个stackoverflow答案为我编写。它只是一个pice代码。我正在阅读和学习使用它。谢谢。规则-我认为$block\u启动时
可以不重置,因为它定义了块范围-一旦块结束,子块将退出。如果子处理>1 block.rule,这将是一个合理的问题-另外,我想你的意思是$line!~/materialieu4/
,不?优雅的解决方案…我的产生空块k、 而您的代码只是跳过了该块的整组行并继续执行下一个blockrule,我测试了用if($line=~/^(status)/)和($line!~/materialieu4/)替换我原来的if条件
。它工作得很好。谢谢。规则。实际上,道蟾蜍很乐意为我写下完整的示例代码作为另一个stackoverflow答案。它只是一个pice代码。我正在阅读和学习它。谢谢。规则-我认为$block_启动时
可以不重置,因为它定义了块的范围-一旦块被重置结束后,sub将退出。如果sub处理>1 block.rule,这将是一个合理的问题-而且,我想你的意思是$line!~/materialeu4/
,不是吗?优雅的解决方案…我的生成空块,而你的只是跳过该块的整组行并继续下一个blockrule,我测试了用I替换我原来的if条件f($line=~/^(status)/)&($line!~/materialieu4/);
。它工作得很好。谢谢。顺便说一句,我选择了稍微灵活一点的方法,为可跳过的块返回空数组,而不是只是默默地跳过它。对于当前的需要,这有点过分了,但Oth可以在以后扩展,以便对此类块进行其他处理