PERL - регулярное выражение, включая все ключи хеша (отсортировано) + удаление пустых полей из $ _ при чтении файла - PullRequest
2 голосов
/ 01 июля 2011

Я работаю над программой, и у меня есть пара вопросов, надеюсь, вы можете помочь:

Сначала мне нужно получить доступ к файлу и получить определенную информацию в соответствии с индексом, полученным из предыдущегошаг, на котором индексы для поиска находятся и хранятся в хэше.

Я искал способ включить все элементы массива в регулярное выражение, которые я могу использовать при поиске файлов, но у меня нетНе смог заставить его работать.В конце концов я нашел способ, который работает:

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

.....

Как мне избавиться от пустого столбца?

Большое спасибо за вашу помощь, Мерче

Ответы [ 4 ]

2 голосов
/ 01 июля 2011

Существует специальная форма 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";

См. Документацию для split на http://p3rl.org/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 голос
/ 01 июля 2011

Позволяет разогреться, уточняя и исправляя часть вашего кода:

# 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;

Это избавит вас от многих головных болей.

0 голосов
/ 04 июля 2011

спасибо за все ваши ответы.Я попробовал разделить форму с помощью '', и это спасло меня от нескольких строк кода.спасибо!

Что касается регулярного выражения, я нашел кое-что, что могло бы сделать все ключи частью строкового выражения с помощью join и quotemeta, но я не смог заставить его работать.Тем не менее я нашел альтернативу, которая работает, но мне больше понравилось решение join / quotemeta

Индексы атомов получены из текстового файла в соответствии с некоторым энергетическим порогом.Позже, в цикле IN_LIG, мне нужно получить доступ к файлу молекулы, чтобы получить больше информации о выбранных атомах, поэтому я использую «индекс» атома в молекуле, чтобы определить, какие строки файла мне нужно прочитать и обработать.Это подпрограмма, в которую я отправляю хеш с индексом атома и другой информацией.

Я попытался это для регулярного выражения:

 my $strings = join "|" map quotemeta,
 sort { $hash->{$b} <=> $hash->{$a}} keys  %($hash);

, но я сделал что-то не так, потому что этовзять все ключи

0 голосов
/ 01 июля 2011

для второго вопроса вы можете использовать эту строку:

@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] ];
}

Позже вы можете искать подробную информацию по интересующим вас индексам и обрабатывать их по мере необходимости.Предполагается, что индекс уникален (имеет свойство ключей).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...