我正在制作一个计划,我有几个问题,希望你能提供帮助:
首先,我需要访问一个文件并根据从上一步获得的索引检索特定信息,在该索引中找到要检索的索引并存储在哈希中。
我一直在寻找一种方法,将所有数组元素都包含在我可以在文件搜索中使用的正则表达式中,但是我还没有能够使它工作。最终我找到了一种有效的方法:
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--;
.....
}
有没有办法创建一个包含所有哈希键的正则表达式?它们是数字,必须进行排序。键指的是IN_LIG中的行索引,其内容类似于:
8 C5 9.9153 2.3814 -8.6988 C.ar 1 MLK -0.1500
密钥可在第0列(8)中找到。我添加了^和\ s +以确保它仅引用第一列。
我的第二个问题是,有时输入文件并不总是相同,并且它们在索引之前包含空格,所以当我从$ _创建数组时,我得到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
答案 0 :(得分:2)
有一种特殊形式的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";
请参阅http://p3rl.org/split(或split
)perldoc 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
}
}
答案 1 :(得分:1)
通过改进和纠正一些代码来让我们热身:
# If these are all numbers, do a numerical sort: <=> not cmp
my @atoms = ( sort { $b <=> $a } keys %{$atome} );
my $natoms = scalar @atoms;
无需循环键,您可以立即将它们插入阵列。您也可以立即对它们进行排序,如果它们是数字,则排序必须是数字,否则您将得到如下类型:1,11,111,2,22,222,......
$natoms
可以通过@atoms
中的值计数直接分配。
while(<IN_LIG>) {
last unless $natoms;
my $key = (split)[0]; # split splits on whitespace and $_ by default
$natoms-- if ($key == $atoms[$natoms - 1]);
}
我不太确定你在这里做了什么,如果这是最好的方法,但是这个代码应该有用,而你的正则表达式不行。在正则表达式中,[]
是元字符。默认情况下拆分会在空格上拆分$_
,因此您无需明确这一点。这种拆分也肯定会删除所有空格。您的空字段很可能是空字符串'',而不是空格''。
比较两个数字的最佳方法不是使用正则表达式,而是使用等于运算符==
。
你的空字段应该通过拆分空格而消失。 split
的默认值为split ' '
。
另外,如果你还没有这样做,你应该使用:
use strict;
use warnings;
它会为你节省很多麻烦。
答案 2 :(得分:0)
对于你的第二个问题,你可以使用这一行:
@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] ];
}
稍后您可以查找您感兴趣的索引的详细信息并根据需要进行处理。这假定索引是唯一的(具有键的属性)。
答案 3 :(得分:0)
感谢您的所有回复。我用''尝试了拆分表单,它为我节省了几行代码。谢谢!
对于正则表达式,我发现了一些可以使所有键成为带有join和quotemeta的字符串表达式的一部分,但我无法使其工作。不过我找到了一个有效的替代方案,但我更喜欢join / quotemeta解决方案
根据某个能量阈值从文本文件中获取原子索引。之后,在IN_LIG循环中,我需要访问分子文件以获得有关所选原子的更多信息,因此我使用分子中的原子“index”来识别我必须阅读和处理的文件行。这是一个子例程,我使用原子索引和其他一些信息发送哈希值。
我为正则表达式尝试了这个:
my $strings = join "|" map quotemeta,
sort { $hash->{$b} <=> $hash->{$a}} keys %($hash);
但是我做错了因为它不会占用所有键