Bash 如何删除所有符合特定条件的行

Bash 如何删除所有符合特定条件的行,bash,perl,awk,Bash,Perl,Awk,我有很多pdb文件,我只想保留那些以^FORMUL开头的行,如果行中有C后跟大于(C3、C4、C5、C6..100等)的数字,我就不应该打印它。第二个条件是,在C、H和N的每一行中,总和应为=6,然后将其删除 因此,整体删除C后接数字大于2>的行,C+O+N的总和为=然后为6 FORMUL 3 HOH *207(H2 O) (print it) FORMUL 2 SF4 FE4 S4

我有很多pdb文件,我只想保留那些以
^FORMUL
开头的行,如果行中有
C
后跟大于(
C3、C4、C5、C6..100等)的数字,我就不应该打印它。第二个条件是,在
C、H和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
中执行此操作,但行之间的差异太大,因此我不确定是否可以执行此操作

所有这些条件都应包括在一起,这意味着应删除
C>2
sum>=6
的所有行。
c1o5n3
应删除<虽然
C
3
,但不应删除code>c3n101

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

#!/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    
}
}
#/usr/bin/perl
严格使用;
使用警告;
我的@行;
我的$file;
我的美元线;

打开($file,Extended
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

正如您所看到的,将其作为一个过滤器来编写可能更容易,它可以打印您想要保留的行。我还按照Unix过滤器模型编写了它(从
STDIN
,写入
STDOUT
),因为这使程序更加灵活(有趣的是,更容易编写!)

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

$ 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;
}
$my_过滤器<5PCZ.pdb>5PCZ.pdb.new
代码如下所示:

$ 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;
}
!/usr/bin/perl
严格使用;
使用警告;
而(){#一次读取一行标准数据
#将数据拆分为空白,但仅分为四列
my@cols=split/\s+/,$\u4;
下一步除非$cols[0]eq‘FORMUL’;
#现在将字母内容提取到散列中以便于访问。
#我们从记录的最后一列中提取字母。
我的%letters=$cols[-1]=~m/([A-Z])(\d+)/g;
#给出我们感兴趣的值,默认值为0
(qw[con])的$letters{$}/=0;
如果$letters{C}>2,则下一步
和$字母{C}+$字母{O}+$字母{N}>=6;
#我想我们可以把这行打印出来;
印刷品;
}

这似乎为您的示例数据提供了正确的输出。我希望注释能够清楚地说明如何调整条件。

如果您尝试使用Perl进行操作,请添加Perl标记并显示您拥有的代码。您的描述非常混乱,因此我并不奇怪您在编码时遇到困难。可能尝试编写3个单独的sim保留或丢弃的ple规则,而不是像你目前拥有的那样混合东西的规则……”“我想与FORMUL保持一致,如果它有其他东西,我不想保留。”。谢谢,我几天前做的,然后我删除了它,但我现在就要写了。。问题是我对行的操作非常不熟练。我可以在脚本中包含像读取文件一样的内容,读取每一行直到结束,如果它以
^FORMUL
开头,那么我在分配条件和删除行id方面有问题,因为它们不符合这些条件附加条件。@djordje,如果没有
C
char,但是出现了
N22
,怎么办?那么我不应该删除它:所以删除所有有
C>2
(C3、C4、C5..)的行而
CON
的总和必须是
=>
。所以应该删除
c1n2o1
的行,尽管
sum
大于
6
C
小于
2
。如果
c3n1o1
这也不应该包括在内,我编辑了这个问题,包括我刚刚写的perl脚本,但我已经完成了分配这两个条件真的很麻烦(我的正则表达式知识有差距)戴夫:谢谢你的回答。是的,我也意识到打印我想保留的行要简单得多。评论让它更容易理解!我必须多练习,才能将思维从生物学转向编程。Cheers@Dave)@PerlDuck:哦,好吧,那不是很有趣吗!谢谢你指出这一点。