Как я могу разобрать только часть файла с Perl? - PullRequest
4 голосов
/ 18 октября 2010

Я абсолютный новичок в Perl, но я слышал, что он отлично подходит для разбора файлов, поэтому я подумал об этом.

У меня есть текстовый файл со следующимпример информации:

High school is used in some
parts of the world, particularly in
Scotland, North America and Oceania to
describe an institution that provides
all or part of secondary education.
The term "high school" originated in
Scotland with the world's oldest being
the Royal High School (Edinburgh) in
1505.

The Royal High School was used as a
model for the first public high school
in the United States, the English High
School founded in Boston,
Massachusetts, in 1821. The precise
stage of schooling provided by a high
school differs from country to
country, and may vary within the same
jurisdiction. In all of New Zealand
and Malaysia along with parts of
Australia and Canada, high school is
synonymous with secondary school, and
encompasses the entire secondary stage
of education.

======================================
Grade1 87.43%
Grade2 84.30%
Grade3 83.00%
=====================================

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

if (m/^%/) {
    do something
}
else {
    skip the line
}

Но что я действительно хочу сделать, так это отслеживать переменную слева и сохранять числовое значение в этой переменной.Итак, после анализа файла мне бы очень хотелось иметь следующие переменные, чтобы в них хранилось значение%.Причина в том, что я хочу создать круговую диаграмму / гистограмму разных марок.

Оценка 1 = 87,43 Оценка 2 = 84,30

...

Не могли бы вы предложить методы, на которые мне следует обратить внимание?

Ответы [ 5 ]

6 голосов
/ 18 октября 2010

Вам понадобится регулярное выражение. Что-то вроде следующего должно работать

while (<>) {
  /(Grade[0-9]+)\s*([0-9]+\.[0-9]+)/;
  $op{$1} = $2;
}

в качестве фильтра. В хеше op будут храниться названия и оценки. Это предпочтительно для автоматического создания экземпляров переменных.

3 голосов
/ 18 октября 2010

Если вы можете гарантировать, что ваши достопримечательности вложены между двумя = с (и не существует нечетного числа этих разграничений в данном файле), оператор триггера здесь удобен:

use strict;    # These two pragmas go a long, ...
use warnings;  # ... long way in helping you code better

my %scores;    # Create a hash of scores

while (<>) {   # The diamond operator processes all files ...
               # ... supplied at command-line, line-by-line

    next unless /^=+$/ .. /^=+$/;  # The flip-flop operator used ...
                                   # ... to filter out only 'grades'

    my ( $name, $grade ) = split;  # This usage of split will break ...
                                   # ... the current line into an array    

    $scores{$name} = $grade;       # Associate grade with name
}
2 голосов
/ 18 октября 2010

Вы хотите использовать хеш. Нечто подобное должно сработать:

my %grades = (); # this is a hash
open(my $fh, "grade_file.txt" ) or die $!;
while( my $line = <$fh> ) {
     if( my( $name, $grade ) = $line =~ /^(Grade\d+)\s(\d+\.\d+\%) ) {
         $grades{$name} = $grade;
     }
}
close($fh);

Ваш %grades хеш будет содержать имя и пары оценок. (Доступ к нему, как my $value = $grades{'Grade1'}

Также просто примечание. Язык называется «Perl», а не «PERL». Многие в сообществе Perl расстраиваются из-за этого: -)

0 голосов
/ 19 октября 2010

См. Ответ Заида для примера использования оператора триггера (это то, что я бы порекомендовал). Однако, если у вас возникнут трудности с этим (иногда DWIMmery может помешать этому), вы также можете явно поддерживать состояние, читая файл построчно:

#!/usr/bin/perl

use strict; use warnings;

my %grades;
my $interesting;

while ( my $line = <DATA> ) {
    if ( not $interesting and $line =~ /^=+\s*\z/ ) {
        $interesting = 1;
        next;
    }
    if ( $interesting ) {
        if ( $line =~ /^=+\s*$/ ) {
            $interesting = 0;
            next;
        }
        elsif ( my ($name, $grade) = $line =~ /^(\w+)\s+(\d+\.\d+%)/ ) {
            # Keep an array in case the same name occurs
            # multiple times
            push @{ $grades{$name} }, $grade;
        }
    }
}

use YAML;
print Dump \%grades;
0 голосов
/ 18 октября 2010

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

Однако, если вы действительно думаете, что хотите это сделать:

while (my $line = <$your_infile_handler>){
   if ($line =~ m/(.*) = ([0-9.]*)){
      $$1 = $2;
   }
}

должен выполнить это.

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