根据Perl中的列值从文件中删除行

时间:2015-05-25 19:54:33

标签: perl

我希望循环遍历文件中的多个文件及其各自的行。我已经成功完成了。我现在想要做的是根据其中一列中的数值删除文件中的行。

如果我有这样的输入:

 XP.sta1    -41.5166    0.0513    0.6842    0.1794    0  CPHI.BHZ   300.2458   -42.2436
 XP.sta2      3.5972    0.0500    0.7699    0.1213    0  E000.BHZ   300.5616     2.5545
 XP.sta3      3.7112    0.0267    0.7813    0.1457    0  E002.BHZ   300.6140     2.6160
 XP.sta4      4.2891    0.0214    0.6870    0.1308    0  E004.BHZ   301.2073     2.6006

其中第九列是我想看的列。我需要在第9列中移除该值(让我们为其分配一个变量$ time),如果该$ time是> 10或小于-10,删除整行。到目前为止,我已经尝试过这个:

unless (($time < -10) || ($time > 10) {     
print OUT2 ($stlat,"  ",$stlon,"  ",$eqlat,"  ",$eqlong,"  ",$eqdepth,"  ",$time,"\n");
}}

但是我得到以下输出:

 XP.sta1    -41.5166    0.0513    0.6842    0.1794    0  CPHI.BHZ   300.2458   2.5545
 XP.sta2      3.5972    0.0500    0.7699    0.1213    0  E000.BHZ   300.5616    2.6160
 XP.sta3      3.7112    0.0267    0.7813    0.1457    0  E002.BHZ   300.6140     2.6006
 XP.sta4      4.2891    0.0214    0.6870    0.1308    0  E004.BHZ   301.2073 

正如您所看到的,整条线路都没有删除 - 只有符合真实值的值才会被删除,除非&#39;条件,然后其他值在第9列中向上移动。如何删除整行,而不仅仅删除第九列?

我希望在哪里编辑我的脚本:

open(TABLEC,$File);
    @tablec = <TABLEC>;
    for ($j = 2; $j < $stop; $j++) {
       chomp ($tablec[$j]);
       ($netSta,$delayTime) = (split /\s+/,$tablec[$j])[1,9] ;  
        } 

在这个for循环中,我循环遍历每个文件,读取从2到&#39;停止&#39;的行,并切断返回字符。我将第9列设置为延迟时间变量。所以我循环遍历每一行,但我还不想打印任何东西(稍后会在我的脚本中)。我只想删除整行,以便稍后在我的脚本中打印行时,第9列值为&gt; abs(10)的行不存在。

3 个答案:

答案 0 :(得分:1)

我只是跳过这一行:

use warnings;
use strict; 

while(<DATA>){
    my @split = split;
    next if $split[8] > 10 or $split[8] < -10;
    print "$_\n";
}
 XP.sta2      3.5972    0.0500    0.7699    0.1213    0  E000.BHZ   300.5616     2.5545
 XP.sta3      3.7112    0.0267    0.7813    0.1457    0  E002.BHZ   300.6140     2.6160
 XP.sta4      4.2891    0.0214    0.6870    0.1308    0  E004.BHZ   301.2073     2.6006

答案 1 :(得分:0)

您还没有足够的代码来诊断问题,但您提出的问题很简单就是这样做了

use strict;
use warnings;

while ( <DATA> ) {
  print unless abs((split)[8]) > 10;
}

__DATA__
 XP.sta1    -41.5166    0.0513    0.6842    0.1794    0  CPHI.BHZ   300.2458   -42.2436
 XP.sta2      3.5972    0.0500    0.7699    0.1213    0  E000.BHZ   300.5616     2.5545
 XP.sta3      3.7112    0.0267    0.7813    0.1457    0  E002.BHZ   300.6140     2.6160
 XP.sta4      4.2891    0.0214    0.6870    0.1308    0  E004.BHZ   301.2073     2.6006

<强>输出

 XP.sta2      3.5972    0.0500    0.7699    0.1213    0  E000.BHZ   300.5616     2.5545
 XP.sta3      3.7112    0.0267    0.7813    0.1457    0  E002.BHZ   300.6140     2.6160
 XP.sta4      4.2891    0.0214    0.6870    0.1308    0  E004.BHZ   301.2073     2.6006

答案 2 :(得分:0)

我认为您的问题已得到解答,请在此处添加一些可以帮助您完成编辑内容的内容

代码上的一些要点

  • 词汇变量的标识符应仅包含小写字母,小数位和下划线。大写字母保留用于全局变量,例如常量和包名称

  • 您应该使用词法文件句柄三参数形式open

  • 您应该始终验证open是否成功。如果失败,您的程序应该die并在die字符串中包含$!的值,以显示为什么操作失败

    这些点一起意味着

    open(TABLEC, $File);
    

    变为

    open my $tablec_fh, '<', $File or die qq{Unable to open "$File" for input: $!};
    
  • 您可以chomp

  • 一次chomp @tablec整个数组
  • 你应该避免使用C风格的for循环,因为它很少是一个不错的选择。 Perl允许你迭代一个范围,你应该利用它。所以

    for ($j = 2; $j < $stop; $j++) { ... }
    

    变为

    for my $j ( 2 .. $stop-1 ) { ... }
    
  • split /\s+/几乎应始终为split ' '。后者是操作符的特殊情况,如果参数字符串具有前导空格,则阻止它返回初始空字段。如果您在没有任何参数的情况下致电split,则默认为split ' ', $_

这里重写了您考虑这些要点的示例代码。我希望它比我以前的答案更合适

open my $tablec_fh, '<', $File or die qq{Unable to open "$File" for input: $!};
my @tablec = <$tablec_fh>;
chomp @tablec;
close $tablec_fh;

for my $i ( 2 .. $stop-1 ) {
  my $row = $tablec[$i];
  my ($net_sta, $delay_time) = (split ' ', $row)[0,8];
  next unless abs($delay_time) <= 10;

  # Do stuff with $row
}