Как проверить, пустые ли несколько переменных в Perl - PullRequest
3 голосов
/ 10 ноября 2010

У меня есть Perl-скрипт, где переменные должны быть инициализированы, прежде чем скрипт сможет продолжить. Длинный оператор if, где я проверяю каждую переменную, является очевидным выбором. Но, возможно, есть более элегантный или лаконичный способ проверки нескольких переменных.

Edit: Мне не нужно проверять наличие «определенных», они всегда определяются пустой строкой, мне нужно проверить, что все они не пустые.

Пример:

my ($a, $b, $c) = ("", "", "");

# If-clauses for setting the variables here

if( !$a || !$b || !$c) {
  print "Init failed\n";
}

Ответы [ 5 ]

8 голосов
/ 10 ноября 2010

Я предполагаю, что empty означает пустую строку, а не просто какое-либо ложное значение.То есть, если 0 или "0" являются действительными значениями после инициализации, принятый в настоящее время ответ даст вам неверный результат:

use strict; use warnings;

my ($x, $y, $z) = ('0') x 3;
# my ($x, $y, $z) = ('') x 3;

for my $var ($x, $y, $z) {
    die "Not properly initialized\n" unless defined($var) and length $var;
}

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

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

use strict; use warnings;

my %params = (
    x => 0,
    y => '',
    z => undef,
);

while ( my ($k, $v) = each %params ) {
    validate_nonempty($v)
        or die "'$k' was not properly initialized\n";
}

sub validate_nonempty {
    my ($v) = @_;
    defined($v) and length $v;
}

Или, если вы хотите перечислить все, что не было должным образом инициализировано:

my @invalid = grep is_not_initialized($params{$_}), keys %params;
die "Not properly initialized: @invalid\n" if @invalid;

sub is_not_initialized {
    my ($v) = @_;
    not ( defined($v) and length $v );
}
8 голосов
/ 10 ноября 2010
use List::MoreUtils 'all';
say 'Yes' if (all { defined } $var1, $var2, $var3);
8 голосов
/ 10 ноября 2010

Что вы подразумеваете под "инициализирован"?Есть значения, которые не являются "undef"?

Для небольшого количества значений прямая проверка, если ИМХО, является наиболее читаемой / поддерживаемой.

if (!$var1 || !$var2 || !$var3) {
    print "ERROR: Some are not defined!"; 
}

Кстати, проверка !$var возможная ошибка в том, что «0» является ложным в Perl, и, следовательно, строка, инициализированная «0», провалит эту проверку.Гораздо лучше использовать $var eq ""

Или еще лучше, разложить вещи по> 3 значениям

if    (!$var1          # Use this if your values are guarantee not to be "0"
    || $var2 eq ""     # This is a LOT better since !$var fails on "0" value
    || $var3 eq "") {

    print "ERROR: Some are not defined!"; 
}

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

# We use "length" check instead of "$_ eq ''" as per tchrist's comment below
if (grep { length } ($var1, $var2, $var3, $var4, $var5, @more_args) ) {
    print "ERROR: Some are not defined!"; 
}

Если вы должны знать, КАКОЕ из значений не определено, вы можете использовать цикл for (оставленный в качестве очевидного упражнения для читателя) или трюк с картой:

my $i = -1; # we will be pre-incrementing
if (my @undefined_indexes = map { $i++; $_ ? () : $i }
                                ($var1, $var2, $var3, $var4, $var5, @more_args) ) {

    print "ERROR: Value # $_ not defined!\n" foreach @undefined_indexes; 
}
7 голосов
/ 10 ноября 2010
use List::Util 'first';

if (defined first { $_ ne "" } $a, $b, $c) {
    warn "empty";
}    
3 голосов
/ 10 ноября 2010

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

if (not($a and $b and $c)) {
   warn(qq(Not all variables are initialized!))
}

Таким образом, вы не ставите префикс не перед каждой переменной, и это не влияет на читабельность. Вы можете использовать List::Util или List::MoreUtils, но они на самом деле не улучшают разборчивость.

Как сказал Синан Юнюр, если вы поместите переменные в хеш, вы можете проанализировать хеш и затем указать, какие переменные не были инициализированы. Это может быть лучше, если таких переменных много, а список постоянно меняется.

foreach my $variable qw(a b c d e f g h i j) {
    if (not $param{$variable}) {
        warn qq(You didn't define $variable\n);
    }
}

Вы можете использовать Getopts::Long, чтобы поместить значения параметров в хеш вместо отдельных переменных. Кроме того, последние версии Getopts::Long теперь могут работать с любым массивом, а не только с @ARGV.

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