2017-02-14 14 views
0

В настоящее время я разделяю файл Perl, содержащий некоторые данные о пользователе/​​пароле, и делаю это успешно, но не удовлетворен моим кодом. Я уверен, что есть лучший способ сделать это в Perl (я новичок). Если бы кто-то мог придумать более легкий способ, который был бы замечательным!Perl Split File В строки и переменные

my $i = 1; 
my $DB; 
my $DBHOST; 
my $DBUSER; 
my $DBPASS;  
my $filename = "some_file"; 
open(my $fh, '<:encoding(UTF-8)', $filename) 
    or die "Could not open file '$filename' $!"; 

while (my $row = <$fh>) { 
    chomp $row; 
    if ($i == 1) { 
     $DB = (split /=/, $row)[1]; 
    } 
    if ($i == 2) { 
     $DBHOST = (split /=/, $row)[1]; 
    } 
    if ($i == 3) { 
     $DBUSER = (split /=/, $row)[1]; 
    } 
    if ($i == 4) { 
     $DBPASS = (split /=/, $row)[1]; 
    } 
    $i++; 
} 
+5

[codereview.stackexchange] (http://codereview.stackexchange.com/) может быть лучшим местом для запроса обзора кода. –

+1

Читайте о строгом, предупреждениях, закрытии дескрипторов файлов и $ i ++ можно заменить на $. в твоем случае. – user3606329

+0

Какую базу данных вы используете? Способ * best * для этого - позволить серверу базы данных анализировать файл учетных данных напрямую. Например, MySQL имеет [файлы параметров] (https://dev.mysql.com/doc/refman/5.7/en/option-files.html), а Postgres имеет [.pgpass] (https: //www.postgresql. орг/документы/9.2/статический/libpq-pgpass.html). – ThisSuitIsBlackNot

ответ

0

map() очень удобно для таких вещей, как это:

my ($DB, $DBHOST, $DBUSER, $DBPASS) = map {$_ =~ /.*?=(.*)/} <$fh>; 

Что происходит:

  • map() работает в списках, поэтому он относится к <$fh> как один
  • для каждого элемента список (строка файла в этом случае), назначьте его в переменную по умолчанию ($_)
  • затем возьмите часть строки, которую мы хотим с помощью регулярного выражения, вернем ее и присвоим ей соответствующую переменную в левой части (на каждой итерации файла каждая из принимающих переменных сдвинут а)
  • регулярное выражение работает следующим образом:

    / .*? # ignore everything, non greedy until we match a = # our delimiter ( # begin capture .* # capture everything until end of line (less the newline char) ) # end capture /

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

Также обратите внимание, что здесь нет ошибки, поэтому, если значение не будет записано, вы получите предупреждения, связанные с неопределенными переменными.

+0

Ничего себе, вы можете объяснить, что именно здесь происходит? Страница документации не слишком полезна. – user2774695

+0

Конечно. Я уточню свой ответ. – stevieb

+0

Я вижу, что '. *?' соответствует любому символу, 0 или более раз (кроме терминаторов строк?), а затем соответствует «=», затем еще раз любой символ 0 или более раз. Тогда карта в основном делает это foreach этих переменных? Как он получает значение после «=» и присваивает его переменной? – user2774695

0

Я думаю, что я покончу с вашими индивидуальными переменными и сохранил информацию о соединении в хеше.

my %db_conn; 

while (<$fh>) { 
    my ($key, $val) = split /=/, $_, 2; 
    $db_conn{$key} = $val; 
} 

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