Как мне сделать эту манипуляцию файла в Perl? - PullRequest
1 голос
/ 15 декабря 2011

поэтому мой файл выглядит следующим образом:

--some comments--
--a couple of lines of header info--
 comp:
  name: some_name_A
  type: some_type
  id:   an id_1
  owner: who owns it
  path:  path_A to more data
 end_comp

 comp:
  name: some_name_B
  type: some_type
  id:   an id_2
  owner: who owns it
  path:  path_B to more data
 end_comp  

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

Что я сделал (просто псевдо):

@filedata = <read_file> #read file in an array
$names_to_search = join("|", @some_names);

while(lines=@filedata)
{
 if( $line =~ /comp:/ )
 {
   $line = <next line>;
   if( $line =~ /name: $names_to_search/ )
   {
    #loop until we find the id
    #remember this index since we need to change this id

    #loop until we find the path field
    #get the path, go to that path, do some perforce commands and obtain new id
    if( id is same as current id ) no action required
    else replace current id with new id
   }
  }
}

Проблема: Моя текущая реализация имеет три цикла while!Есть ли лучший / эффективный / элегантный способ сделать это?

Ответы [ 3 ]

4 голосов
/ 15 декабря 2011

Вы написали файл конфигурации в произвольном формате, а затем пытаетесь разобрать его вручную.Вместо этого, почему бы не записать файл в установленном формате, таком как YAML или INI, а затем использовать существующие модули для его анализа?

Например, используя YAML:

use YAML::Any;
my @data = YAML::Any::LoadFile($filename) or die "Could not read from $filename: $!":

# now you have your data structure in @data; parse it using while/for/map loops.

Вы можете прочитатьINI-файлы с Config :: INI или Config :: INI :: Simple .

1 голос
/ 15 декабря 2011

Поскольку ни один из двух блоков не может иметь одинаковое значение name, вы можете использовать ссылку на хэш ссылок на хэш:

{
  "name1"=>{type=>"type1",id=>"id1",owner=>"owner1",path=>"path1"},
  "name2"=>{type=>"type2",id=>"id2",owner=>"owner2",path=>"path2"},
  #etc
}

Что-то вроде этого должно работать (Предупреждение: не проверено):

use strict;
use warnings;

open(my $read,"<","input_file.txt") or die $!;

my $data={};
my $current_name=""; #Placeholder for the name that we're currently using.

while(<$read>)
{
  chomp; #get rid of trailing newline character.

  if(/^\s*name:\s*([\w]+)\s*$/) #If we hit a line specifying a name, 
                                #then this is the name we're working with
  {
    $current_name=$1;
  }
  elsif(/^\s*(type|id|owner|path):\s*([\w]+)\s*$/) #If it's data to go with the name, 
                                                   #then assign it.
  {
    $data->{$current_name}->{$1}=$2;
  }
}

close($read);

#Now you can search your given array for each of the names and do what you want from there.

Однако, если вы можете, я действительно рекомендую хранить данные в вашем файле в каком-то стандартизированном формате (YAML, INI, JSON, XML и т. Д.), А затем анализировать их соответствующим образом.Я также должен добавить, что этот код зависит от каждого name, появляющегося перед соответствующими type, id, owner и path.

1 голос
/ 15 декабря 2011

Вот какой-то псевдокод:

index = 0;

index_of_id = 0; // this is the index of the line that contains the current company id

have_company = false; // track whether we are processing a copmany

while (line in @filedata)
{
  if (!have_company)
  {
    if (line is not "company") 
    {
      ++index;
      continue;
    }
    else
    {
      index_of_id = 0;
      have_company = true;
    }
  }
  else
  {
    if (line is "end_comp")
    {
      have_company = false; // force to start looking for new company
      ++index;
      continue;
    }

    if (line is "id")
      index_of_id = index;  // save the index

    if (line is "path")
    {
      // do your stuff then replace the string at the index given by index_of_id
    }
  }
  // line index
  ++index; 
}

// Now write the modified array to file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...