Bash 如何删除所有符合特定条件的行
我有很多pdb文件,我只想保留那些以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
^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,ExtendedAwk
解决方案:
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:哦,好吧,那不是很有趣吗!谢谢你指出这一点。