Regex 如何检测哪一行I';我在用Perl处理吗?
获取了一个如下所示的文本文件:Regex 如何检测哪一行I';我在用Perl处理吗?,regex,perl,Regex,Perl,获取了一个如下所示的文本文件: 200.0 250.0 300.0 350.0 400.0 162:02:10 017:01:56 017:08:18 011:16:22 008:40:18 580.0 600.0 620.0 640.0 660.0 004:04:01 001:47:27 007:25:29 017:44:53 003:07:34 尝试将第1行和第3行解析为“值”,将第2行和第4行解析为
200.0 250.0 300.0 350.0 400.0
162:02:10 017:01:56 017:08:18 011:16:22 008:40:18
580.0 600.0 620.0 640.0 660.0
004:04:01 001:47:27 007:25:29 017:44:53 003:07:34
尝试将第1行和第3行解析为“值”,将第2行和第4行解析为“时间”
我的代码:
if($line =~ /^\d[^:]*\d/){
my @values = split(/\s/,$line);
}
elsif($line =~/^\d+:\d+:\d+/){
my @time = split(/\s/,$line);
}
问题:
始终匹配第一个正则表达式。我对regex#1的理解是,它将匹配一行,该行以一个数字开头,后跟任何不是“:”的值,任何次数,后跟另一个数字。第1行和第3行满足以下regex:
(?m)^(?:\s*\d+\.\d+\s*)+$
试试这个:
open(FILE, 'yourfile.txt') or die("Could not open file!");
foreach $line (<FILE>) {
if($line =~ /(?m)^(?:\s*\d+\.\d+\s*)+$/) {
print $line;
}
}
打开(文件'yourfile.txt')或死亡(“无法打开文件!”);
foreach$行(){
如果($line=~/(?m)^(?:\s*\d+\.\d+\s*)+$/){
打印$行;
}
}
只需更改支票的顺序:
if($line =~/^\d+:\d+:\d+/){
...
}
elsif($line =~ /^\d[^:]*\d/){
...
}
发生这种情况是因为第2行和第4行确实包含第一个正则表达式的模式 也许你可以简单地检查一行是否有冒号,这样就足够了?像这样:
my @time;
my @values;
if($line =~ /:/){
@time = split(/\s+/,$line);
}
else{
@values = split(/\s+/,$line);
}
第一个正则表达式每次都匹配的原因是它检测到任何以数字开头的字符串可以有任意数量的字符(除了:),然后有另一个数字。这意味着第2行将匹配冒号前的前三个字符
你也可以在这行的末尾进行匹配,或者做一些更简单的事情,比如只匹配冒号。其他答案都集中在正则表达式上。但是还有另一种方法可以告诉你在文件中的位置 如果确定行始终交替,并且顺序相同,则可以使用
$。
获取正在处理的行号
这仅适用于奇数行上的值始终和偶数行上的时间始终的情况
my@times_和_值;
我的美元价值;
while(我的$line=){
如果($.%2){
$values=parse_值($line);
}
否则{
my$times=parse_times($line);
推送@times_和_值,[$times,$values]
如果定义了$value和$times;
}
}
然后,解析函数可以处理行的验证和分解。使用为每种类型定制的正则表达式来拒绝不正确的值并进行任何解析。您可以抛出致命错误或发出警告。上面的代码将跳过时间/值对,这两个部分的任一部分都无法解析。此外,如果在第一行和第三行中有真正的空格(在开始时,您可能需要考虑如何匹配那些)。太棒了,不敢相信我没有看到。我仍然不明白为什么regex#1在存在“:”时匹配。@Isaacs,因为模式只锚定到字符串的开头。(""一")式的英文文本为:;行的开头,后跟一个数字,后跟0个或更多非:字符(包括数字…),后跟一个数字,这是图案的结尾,因此任何内容都可以位于行的其余部分,包括“:”!您最好使用/\d+\.-d/(一个或多个数字后跟一个文字点,后跟一个数字)@time和@values前面的“my”肯定会降低所有这些的有用性。+1是简单的答案。您的正则表达式需要一个量词:/\s+/
。另外,确定行类型的另一种方法是避免使用正则表达式,并使用更快的index
函数。
my @time;
my @values;
if($line =~ /:/){
@time = split(/\s+/,$line);
}
else{
@values = split(/\s+/,$line);
}
my @times_and_values;
my $values;
while( my $line = <DATA> ) {
if( $. % 2 ) {
$values = parse_values($line);
}
else {
my $times = parse_times($line);
push @times_and_values, [$times, $values]
if defined $values and defined $times;
}
}