PERL——正则表达式,包括所有散列键(已排序)和#x2B;正在从文件读取中的$删除空字段

PERL——正则表达式,包括所有散列键(已排序)和#x2B;正在从文件读取中的$删除空字段,perl,Perl,我正在做一个项目,我有几个问题,希望你能帮助我: 首先,我需要访问一个文件并根据从上一步获得的索引检索特定信息,在该步骤中,要检索的索引被找到并存储在散列中 我一直在寻找一种在正则表达式中包含所有数组元素的方法,我可以在文件搜索中使用它,但我一直无法让它工作。最终我找到了一种可行的方法: my @atoms = (); my $natoms=0; foreach my $atomi (keys %{$atome}){ push (@atoms,$atomi); $natoms++; } @at

我正在做一个项目,我有几个问题,希望你能帮助我:

首先,我需要访问一个文件并根据从上一步获得的索引检索特定信息,在该步骤中,要检索的索引被找到并存储在散列中

我一直在寻找一种在正则表达式中包含所有数组元素的方法,我可以在文件搜索中使用它,但我一直无法让它工作。最终我找到了一种可行的方法:

my @atoms = ();
my $natoms=0;

foreach my $atomi (keys %{$atome}){
push (@atoms,$atomi);
$natoms++;
}
@atoms = sort {$b cmp $a} @atoms;
然后我将其用作正则表达式,如下所示:

while (<IN_LIG>){
if (!$natoms) {last;}
......
if ($_ =~ m/^\s*$atoms[$natoms-1]\s+/){
    $natoms--;  
    .....
}
该键位于第0(8)列中。我添加了^s和\s+,以确保它只引用第一列

我的第二个问题是,有时输入文件并不总是相同的,它们使索引前包含空格,因此当我从$\uu创建数组时,我得到column0=“”,而不是column0=8

我不明白为什么在split命令中没有消除这个“空列”,而且我在删除它时遇到了一些麻烦。这就是我所做的:

@info = split (/[\s]+/,$_);

if ($info[0] eq " ") {splice (@info, 0,1);} # also tried $info[0] =~ m/\s+/
当我打印数组@info时,我得到:

Array: 

Array: 8

Array: C5

Array: 9.9153

Array: 2.3814

.....
我怎样才能去掉这个空列

非常感谢你的帮助
Merche

对于第二个问题,您可以使用以下行:

@info = $_ =~ m{^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)}xms;
为了从每行捕获9个项目(假设它们不包含空格)

第一个问题我不明白

更新:我将读取文件的所有行,并以$info[0]作为键,[@info[1..8]]作为值在散列中使用它们。然后,您可以按索引查找条目

my %details;
while (<IN_LIG>) {
    @info = $_ =~ m{^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)}xms;
    $details{ $info[0] } = [ @info[1..$#info] ];
}
my%详细信息;
而(){
@info=$\u=~ m{^\s*(\s+)\s+(\s+)\s+(\s+)\s+(\s+)\s+(\s+)\s+(\s+)\s+(\s+)\s+)\s+(\s+)}xms;
$details{$info[0]}=[@info[1..$#info]];
}

稍后,您可以查找感兴趣的索引的详细信息,并根据需要进行处理。这假设索引是唯一的(具有键的属性)。

有一种特殊形式的
split
,它将删除前导空格和尾随空格。看起来像这样,试试看:

my $line = '  begins  with    spaces  and ends   with   spaces    ';
my @tokens = split ' ', $line;
# This prints |begins:with:spaces:and:ends:with:spaces|
print "|", join(':', @tokens), "|\n";
请参阅位于(或使用
perldoc split
)的
split
文档

此外,程序的第一部分可能更简单,如下所示:

my @atoms = sort {$b cmp $a} keys %$atome;
my $natoms = @atoms;
但是,你们对原子的最终目标是什么?如果您只是想验证所提供的原子是否确实在文件中,则无需对其进行排序,也无需对其进行计数:

my @atoms = keys %$atome;
while (<IN_LIG>){
    # The atom ID on this line
    my ($atom_id) = split ' ';
    # Is this atom ID in the array of atom IDs that we are looking for
    if (grep { /$atom_id/ } @atoms) {
        # This line of the file has an atom that was in the array: $atom_id
    }
}
my@atoms=keys%$atome;
而(){
#这行上的原子ID
我的($atom_id)=拆分“”;
#这是我们正在寻找的原子ID数组中的原子ID吗
if(grep{/$atom_id/}@atoms){
#文件的这一行有一个数组中的原子:$atom\u id
}
}

让我们通过优化和更正部分代码来热身:

# If these are all numbers, do a numerical sort: <=> not cmp
my @atoms = ( sort { $b <=> $a } keys %{$atome} ); 
my $natoms = scalar @atoms;
我不确定您在这里做什么,也不确定这是否是最好的方法,但这段代码应该可以工作,而您的正则表达式不能。在正则表达式中,
[]
是元字符。默认情况下,“拆分”会在空白处拆分
$\uu
,因此您不需要对此进行明确说明。此拆分也肯定会删除所有空白。您的空字段很可能是空字符串“”,而不是空格“”

比较两个数字的最佳方法不是使用正则表达式,而是使用相等运算符
=

您的空字段应该通过在空格上拆分而消失。
split
的默认值是
split'

此外,如果您还没有这样做,您应该使用:

use strict;
use warnings;

这会帮你省去很多麻烦。

谢谢你的回复。我尝试使用“”拆分表单,它为我节省了几行代码。谢谢

至于正则表达式,我发现可以使用join和quotemeta将所有键作为字符串表达式的一部分,但我无法使其工作。尽管如此,我还是找到了一个可行的替代方案,但我更喜欢join/quotemeta解决方案

原子索引是根据某种能量阈值从文本文件中获取的。稍后,在in_LIG循环中,我需要访问分子文件以获得有关所选原子的更多信息,因此我使用分子中的原子“索引”来确定我必须读取和处理文件的哪些行。这是一个子例程,我向它发送一个包含atom索引和一些其他信息的哈希

我在正则表达式中尝试了这个:

 my $strings = join "|" map quotemeta,
 sort { $hash->{$b} <=> $hash->{$a}} keys  %($hash);
my$strings=join“|”映射quotemeta,
排序{$hash->{$b}$hash->{$a}}键%($hash);

但是我做了一些错误的事情,因为它不会占用所有的键。

grep{$\u==$atom\u id}@atoms
可能会更好。TLP是对的。这里不需要正则表达式。但我可能会使用“eq”而不是“==”,因为我知道在分子文件格式中,id有时会有字母后缀。
use strict;
use warnings;
 my $strings = join "|" map quotemeta,
 sort { $hash->{$b} <=> $hash->{$a}} keys  %($hash);