如何删除符合特定条件

时间:2018-01-10 08:27:36

标签: bash perl awk

我有一些pdb文件,我想只保留那些以^FORMUL开头的行,如果行有C后面跟着大于(C3,C4,C5,C6..100 etc)的数字然后我不应该打印它。第二个条件是,C, H and N中每一行的总和应为>= 6,然后将其删除

因此,请完全删除C后面的数字超过2>的数字,C+O+N的总和为>=,然后是6。

FORMUL   3  HOH   *207(H2 O)    (print it)                                     
FORMUL   2  SF4    FE4 S4       (print it)                                                
FORMUL   3  NIC    C5 H7 N O7   (don't print, there is C5 and sum is more then 6)                                               
FORMUL   4  HOH   *321(H2 O)    (print it)                                                
FORMUL   3  HEM    2(C34 H32 FE N4 O4)  (don't print, there is C34)

我曾尝试在perl中进行此操作,但线条彼此之间存在太多差异,因此我不确定是否可以这样做。

在所有这些条件中,chould应包含在一起,这意味着应删除C>2sum>=6的所有行。 应删除C1 O5 N3; C3 N1 01 C3后,不应删除#!/usr/bin/perl use strict; use warnings; my @lines; my $file; my $line; open ($file, '<', '5PCZ.pdb') or die $!; while (my $line = <$file>) { if ($line =~ m/^FORMUL/) { push (@lines, $line); } } close $file; #print "@lines\n"; foreach $line(@lines) { if ($line eq /"C"(?=([0-2]))/ ) { elsif ($line eq "Sum of O,N & C is lt 6") print @lines } }

在perl中,我不知道如何分配这两个条件。在这里,我写了相反的情况,不删除,但如果不满足这两个条件,打印这些行。

ORDER BY

2 个答案:

答案 0 :(得分:2)

扩展 Awk 解决方案:

awk -F'[[:space:]][[:space:]]+' \
    '/^FORMUL/{ 
         if ($4 !~ /\<C/) print; 
         else { 
             match($4, /\<C[0-9]+/); 
             c=substr($4, RSTART+1, RLENGTH); 
             if (c > 2) next; 
             else { 
                 match($4, /\<O[0-9]+/); 
                 o=substr($4, RSTART+1, RLENGTH); 
                 match($4, /\<N[0-9]+/); 
                 n=substr($4, RSTART+1, RLENGTH); 
                 if (c+o+n < 6) print 
             }
         } 
     }' 5PCZ.pdb

输出:

FORMUL   3  HOH   *207(H2 O)
FORMUL   2  SF4    FE4 S4
FORMUL   4  HOH   *321(H2 O)

答案 1 :(得分:2)

正如您所见,将其编写为打印您要保留的行的过滤器可能更容易。我也在Unix过滤器模型之后编写了这个(从STDIN读取,写入STDOUT)因为这使得程序更加灵活(而且,有趣的是,更容易编写!)

假设您在Linux(或类似版本)上运行该程序并且您的代码位于名为my_filter的可执行文件中(我建议使用更具描述性的名称!),那么您可以这样称呼它:< / p>

$ my_filter < 5PCZ.pdb > 5PCZ.pdb.new

代码如下所示:

#!/usr/bin/perl

use strict;
use warnings;

while (<>) { # read from STDIN a line at a time
  # Split data on whitespace, but only into four columns
  my @cols = split /\s+/, $_, 4;

  next unless $cols[0] eq 'FORMUL';

  # Now extract the letter stuff into a hash for easy access.
  # We extract letters from the final column in the record.
  my %letters = $cols[-1] =~ m/([A-Z])(\d+)/g;

  # Give the values we're interested in, a default of 0
  $letters{$_} //= 0 for (qw[C O N]);

  next if $letters{C} > 2
    and $letters{C} + $letters{O} + $letters{N} >= 6;

  # I think we can then print the line;
  print;
}

这似乎为您的示例数据提供了正确的输出。我希望这些评论能够明确如何调整条件。