2011-01-24 13 views
6

G'Day,W tym hashe w hashe w Perlu

Obecnie pracuję nad tworzeniem dużych skrótów z wielu mniejszych skrótów. Powiedzmy, że te mniejsze skróty są zdefiniowane w pliku, a następnie mogą być włączone przez większy skrót.

Na przykład, spójrzmy na kilka małych mieszań

plików personcontact.pl:

return { 
      \'firstname\' => { 
       \'__type\' => \'String\' 
      }, 
     \'lastname\' => { 
      \'__type\' => \'String\' 
      }, 
     %{include("/tmp/address.pl")} 
    } 

pliku address.pl:

return { 
     \'address\' => { 
     \'street\' => { 
      \'__type\' => \'String\' 
      }, 
     \'unit\' => { 
      \'__type\' => \'String\', 
      \'__validation_function\' => { 
       \'is_a_number\' => \'\' 
      }, 
      \'__schema_constraints\' => { 
       \'is_not_null\' => \'\' 
      } 
     }, 
     \'suburb\' => { 
      \'__type\' => \'String\' 
     }, 
     \'__type\' => \'ARRAY\' 
     } 
    } 

I mam znaczną liczbę tych ...

Sposób, w jaki próbuję odtworzyć, ma h używa include podprogramu, który wygląda tak:

sub include { 
my ($filename) = @_; 
my $file; 
open(my $fh, "<", $filename) or die ("FILEOPEN: $!"); 
while(my $line = <$fh>) { $file .= $line; } 
my $result = eval $file; 
die("EVAL: [email protected]") if [email protected]; 
close($fh) or die("FILECLOSE: $!"); 
return $result; 
} 

Wiem musi robić coś złego, ale nie jestem pewien, co. Wciąż dostaję błędy takie jak Useless use of a variable in void context at (eval 11) line 4, <SCHEMAFILE> line 6 lub Odd number of elements in anonymous hash at (eval 11) line 5, <SCHEMAFILE> line 6. Nie jestem pewien, jak znaleźć (eval 11) linię 4-3, linia 6. Wszelkie sugestie dotyczące użycia debuggerów Perla lub jakichkolwiek wskazówek, które mogą być niewłaściwe, zostaną docenione.

Dzięki!

+2

Nie trzeba czytać wiersz po wierszu. Użyj "trybu slurp", wstawiając 'local $ /;' przed odczytaniem pliku, i zmień 'while (my $ line ...)' na 'my $ line = <$fh>;'. – Mikel

+0

Dzięki za napiwek! Jak mogłeś się domyślić, jestem całkiem nowy w Perlu :) –

+3

Coś jak YAML może być bardziej odpowiednie. http://search.cpan.org/dist/YAML/lib/YAML.pm – Mikel

Odpowiedz

11

Witamy w Perlu. Mam nadzieję, że dobrze się uczysz i go używasz.

Do firmy, od czego zacząć? Mam tu wiele do powiedzenia.

Po pierwsze niepotrzebne jest ładowanie danych przez ocenę plików. Jeśli chcesz tylko szeregować dane, spróbuj JSON::XS lub YAML lub nawet Storable. Jeśli chcesz plik konfiguracyjny, istnieje wiele, wiele modułów w CPAN, które pomagają w tym zadaniu. Sprawdź Config::Any.

Jeśli chcesz utworzyć struktury danych do załadowania przez eval (co nie jest dobrym pomysłem), Data::Dumper generuje kod perl potrzebny do utworzenia dowolnych struktur danych, które do niego przesyłasz. Głównym powodem, dla którego o tym wspominam, jest to, że jest o wiele bardziej użyteczny jako pomoc w debugowaniu niż serializator.

Teraz że jest pod opieką, jeżeli chcesz załadować plik i oceniać go (ponownie, nie najlepszy pomysł w prawie każdym przypadku), to powinno być patrząc na do lub require.

my $stuff = do 'address.pl'; 

Ale nie rób tego. String eval to narzędzie, które na ogół najlepiej pozostawić nieużywane. 99% czasu, jeśli planujesz używać eval string, zatrzymaj się i pomyśl o innym sposobie rozwiązania problemu. Do to niejawna ewaluacja, więc też się liczy.

Perl oferuje wiele narzędzi do wykonywania ryzykownych i potężnych magii. Duża część stania się wykwalifikowanym programistą Perla polega na zrozumieniu, jakie rzeczy są ryzykowne, dlaczego i kiedy ma sens ich użycie. Nie oczekuj, że Perl urodzi cię ogrodzeniem i bramą, abyś był bezpieczny. Poważnie rozważ odebranie kopii Effective Perl Programming lub Perl Best Practices. Jako początkujący, wiele przejdzie ci przez głowę, kiedy czytasz po raz pierwszy, ale każda książka może być świetnym odniesieniem, gdy będziesz wzrastać i uczyć się.

Następny temat, co na świecie próbujesz osiągnąć za pomocą tych wszystkich zbieranych cytatów? Boli mnie patrzeć na te rzeczy! Perl ma numer some very, very nice quoting operators, którego możesz użyć, aby uniknąć bałaganu z wymykającymi się cytatami w literalnych ciągach znaków.

Przecinek grubszy przecina automatycznie lewą stronę (LHS) tak, jakby był tylko alfanumeryczny. Ale umieszczenie wszystkich cytatów i ucieczek czyni rzeczy naprawdę podejrzanymi.

Kiedy mówisz \'address\' => {}, Perl widzi to jako \, operator "pobierz odniesienie" zastosowany do literału łańcuchowego. W tym przypadku nieokreślony ciąg literałowy, ponieważ po pierwszej nie oferuje się bez żadnej zmiany wartości '.

Jeśli celem jest wykorzystanie 'address', cytaty i wszystko jako klucz hash, można to zrobić:

my %foo = ("'address'" => 'blah'); 

Jeśli nie chcesz, cytaty, które wydaje się być o wiele bardziej zwykły przypadek użycia, po prostu wykonaj:

my %foo = (address => 'blah'); 

Do komunikatów o błędach, które otrzymujesz! Perl ma całkiem niezłe komunikaty o błędach, gdy dowiesz się, co one oznaczają. Do tego czasu może być trochę trudno zrozumieć ich znaczenie. Na szczęście Perl jest dostarczany ze skryptem o nazwie splain: poręczne narzędzie typu dandy, które będzie wyjaśniać komunikaty o błędach znacznie bardziej szczegółowo. Możesz także użyć modułu diagnostics, aby automatycznie otrzymywać te same, rozszerzone komunikaty o błędach.

Teraz, gdy pisałem ten zrobiłbym coś wzdłuż tych linii:

gen_schema_files.pl - plik do pisania JSON pliki schematów. Jeśli chcesz, możesz ręcznie edytować swoje schematy. Możesz również skonfigurować wyjście, aby było ładniejsze, jeśli chcesz poprawić czytelność.

#!/usr/bin/perl 

use JSON::XS; 
use File::Spec; 

use constant BASEDIR => '.'; 

# Key is the file name, value is the data to put into the file. 
my %schemata = (
    'address.json' => { 
     address => { 
      street => { __type => 'String' }, 
      unit => { 
       __type => 'String', 
       __validation_function => { is_a_number => '' }, 
       __schema_constraints => { is_not_null => '' } 
      }, 
      suburb => { __type => 'String' }, 
      __type => 'ARRAY' 
     }, 
    }, 

    'person_contact.json' => { 
     firstname => { __type => 'String' }, 
     lastname => { __type => 'String' }, 

     # Use a special key to indicate that additional files should be 
     # loaded into this hash. 
     INCLUDE => [qw(address.json)], 
    }, 

    # And so forth 
); 

for my $schema (keys %schemata) { 
    my $path = File::Spec->catfile(BASEDIR, $schema); 

    open my $fh, '>', $path 
     or die "Error opening '$path' for writing - $!\n"; 

    print $fh encode_json $schemata{$schema}; 
} 

load_schemas.pl - jest to kod, który ładuje schematy i robi rzeczy. Mój zostaje załadowany. Nie mam pojęcia, co robisz z danymi ...

#!/usr/bin/perl 
use strict; 
use warnings; 

use Data::Dumper; 

use JSON::XS; 
use File::Spec; 

use constant BASEDIR => '.'; 


my $schema = load_schema('person_contact.json'); 

print Dumper $schema; 


sub load_schema { 
    my $file = shift; 

    my $path = File::Spec->catfile(BASEDIR, $file); 

    open my $fh, '<', $path 
     or die "Error opening file '$path' - $!\n"; 

    my $json = join '', <$fh>; # reads a list of lines and cats them into one string. 
           # One way to slurp out of many. 

    my $schema = decode_json($json); 

    # Handle the inclusion stuff: 

    if(exists $schema->{INCLUDE}) { 
     # Copy the files to load into an array. 
     my @loadme = @{$schema->{INCLUDE}}; 
     # delete the magic special include key. 
     delete $schema->{INCLUDE}; 

     # Load each file and copy it into the schema hash. 
     for my $load (@loadme) { 
      my $loaded = load_schema($load); 

      # This is a bit of weird syntax. 
      # We are using a hash slice assignment to copy the loaded data into the existing hash. 
      # keys and values are guaranteed to come out in the same (random) order as each other. 
      # the @{$foo}{blahbhal} is how you dereference a hash reference as a slice. 
      @{$schema}{keys %$loaded} = values %$loaded; 
     } 
    } 

    return $schema; 
} 

Mam pomijane kilka rzeczy, ale starałem się zostawić komentarz z wystarczająco warunków (słownictwo, a nawet żargonie, jeśli lubisz), aby umożliwić Ci opłacalne wyszukiwania.

Powyższy kod ma kilka wad. Nie sprawdza on żadnych kolistych inkluzji (będzie działał przez długi czas i ostatecznie zapełni pamięć i awarię - nie tak dobrze). Wybór magicznego klucza może nie być dobry. I prawdopodobnie jest ich jeszcze więcej, o których jeszcze nie pomyślałem.

Perldoc to niesamowity zasób, ale jest tak wiele, że uczenie się znajdowania rzeczy zajmuje trochę czasu. Spójrz na Perl Data Structures Cookbook i Arrays of Arrays tutorial. Jako początkujący odkryłem, że Perl Functions by Category section of perlfunc jest niezwykle pomocny.

Myślę, że przestanę, skoro napisałem więcej niż wystarczająco dużo tekstu, aby oślepić przeciętnego człowieka. Mam nadzieję, że ta praca jest dla ciebie pomocna. Powitaj, jeszcze raz i udanego wieczoru (dostosuj się do czasu lokalnego, kiedy znajdziesz tę odpowiedź).

Powiązane problemy