Насколько ужасен мой Perl? Скрипт, который берет IP-адреса и возвращает полностью определенные доменные имена

Приглашаю тебя, рви мне новую.

Этот код выполняет свою работу. Он берет файл .txt, содержащий список IP-адресов, и записывает файл, содержащий их соответствующие полностью определенные доменные имена.

Я хочу знать, чем плохо написан этот код. Какие здесь вредные привычки?

Я новичок в Perl и программировании. Мне удалось собрать это с помощью google и trail and error. Было приятно заставить его работать, но, пожалуйста, скажите мне, как я могу улучшить его.

use strict;
use warnings;
use Socket;
use autodie;


my $filename = 'IPsForFQDN.txt';
#File with list of IPs to lookup.
#One IP address per line like so:
#10.10.10.10
#10.10.10.11
#10.10.10.12
#etc...


open(my $fh, '<:encoding(UTF-8)', $filename)
    or die "Could not opne file '$filename' $!";
my $fqdn = '';

while (my $row = <$fh>) {
    chomp $row;

    print "$row\n";
    $fqdn = gethostbyaddr(inet_aton($row), AF_INET);
    print $fqdn;
    print "\n";
    open FILE, ">>fqdn.txt" or die $!;
    print FILE $fqdn;
    print FILE "\n";
    close FILE;

}
print "done\n";

Например, нужна ли строка {chomp $ row;}? У меня НЕТ ИДЕИ, что он делает.

Я в равной степени озадачен всем, что касается {or die $ !;}.


person ch1rh0    schedule 06.03.2014    source источник
comment
Если ваш код уже работает, этот вопрос больше подходит для codereview.stackexchange.com.   -  person ThisSuitIsBlackNot    schedule 06.03.2014
comment
В основном хорошо выглядит. Мне нечего сказать, чего не сказал бы Perl::Critic.   -  person mob    schedule 06.03.2014
comment
Быть кандидатом в однострочник достаточно просто: perl -MSocket -nwe 'my $fqdn = gethostbyaddr(inet_aton($_), AF_INET); print $fqdn? $fqdn :"", "\n";' IPsForFQDN.txt >fqdn.txt   -  person R Perrin    schedule 06.03.2014


Ответы (3)


$! сообщает, почему что-то не удалось. Здесь, если вам не удалось открыть файл, будет указана причина сбоя. perlvar имеет раздел на error-переменные.

Вы используете chomp для удаления символа новой строки из конца каждой строки.

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

person Dr.Avalanche    schedule 06.03.2014

Вы постоянно открываете fqdn.txt для каждой написанной вами строчки. Я бы просто открыл его перед петлей и закрывал в конце.

Да, и вы используете автодобавку, поэтому or die в этом нет необходимости.

Да, и вы также использовали для этого open старый стиль, а не новый стиль, открытый для чтения файла.

person Richard Huxton    schedule 06.03.2014

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

Надеюсь это поможет...

use strict;
use warnings;
use Socket;

# initialize variables here.
my $filename = "IPsForFQDN.txt";

# open both file handles - once only
# Note safer expression using 2 commas
open(FH, "<", $filename)
        or die "Could not opne file '$filename' $!";

# open FILE for appending
open FILE, ">>", "fqdn.txt" or die $!;

# use foreach instead of while - easier syntax (may provoke discussion ;-) )
# replaced $fh for FH - use file handles throughout for consitency
foreach my $row ( <FH> )
{
    chomp $row;

    # put a regex check in for comments

    if( $row !~ m/^#/ )
    {
        printf ("Row in file %s \n", $row );

        # initialize $fqdn here to keep it fresh
        my $fqdn = gethostbyaddr(inet_aton($row), AF_INET);

        # formatted print to screen (STDOUT)
        printf ("FQDN %s \n", $fqdn);

        # formatted print to output file
        printf FILE ("%s \n", $fqdn);
    }
}

# close both file handles - once only
close FILE;
close FH;

print "done\n";
person thonnor    schedule 06.03.2014
comment
О да, в паре мест я заменил одинарные кавычки на двойные кавычки для единообразия. Также я предпочитаю использовать двойные кавычки, а не одинарные - это связано с тем, что системы UNIX не заменяют переменные в одинарных кавычках #MyIssueWithSingleQuotes :) - person thonnor; 06.03.2014
comment
В качестве стандарта рекомендуется использовать лексические дескрипторы файлов при открытии файлы и избегайте голым словом дескрипторы файлов (за некоторыми исключениями). - person Kenosis; 06.03.2014
comment
Чем foreach проще, чем while? Что еще хуже, вы считываете весь файл в память, когда вызываете <> в контексте списка, что совершенно не нужно, так как вы в любом случае просто повторяете его построчно. И, как сказал Кенозис, используйте лексические дескрипторы файлов (my $fh) вместо typeglobs (FH), которые имеют глобальную область видимости. - person ThisSuitIsBlackNot; 06.03.2014
comment
Я полагаю, когда я говорю «проще», я имею в виду, что это мой предпочтительный способ итерации по списку. While это нормально, но я предпочитаю использовать это, когда говорю о выполняемых условиях (while $a = true) Я думаю, что одна из сильных сторон Perl - это многословный синаткс, в котором вы можете почти писать настоящие предложения foreach $line ( @list ) Что касается использования лексических файловых дескрипторов - опять же, typeglobs - это то, о чем я упоминал использование и является моим предпочтительным синтаксисом. Это должен быть огромный список IP-адресов, чтобы иметь большое влияние на ресурсы памяти. В этом случае тестирование выявит это, и потребуется переосмысление. - person thonnor; 07.03.2014
comment
Иметь свои личные предпочтения - это нормально, но вы продвигаете плохие практики на публичном форуме. Возможно, вы не знаете, почему не следует использовать typeglobs. Что касается памяти, если вы можете гарантировать, что ваш входной файл всегда будет маленьким, даже после того, как вы прекратили поддержку кода и он используется для чего-то, чего вы никогда не ожидали, во что бы то ни стало, запихните его в память. Я не могу дать такой гарантии относительно кода, который пишу. Кроме того, действительно ли while (my $row = <$fh>) так сложно читать? - person ThisSuitIsBlackNot; 07.03.2014