В Perl, как я могу кратко проверить, определяется ли $variable и содержит строку ненулевой длины?

Вы могли бы хотеть посмотреть здесь и здесь .

Немного примера кода из первой ссылки:

'0385503954');
// define path to server application
$serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter';
//define method namespace
$namespace="urn:xmethods-BNPriceCheck";
// create client object
$client = new soapclient($serverpath);
// make the call
$price = $client->call('getPrice',$param,$namespace);
// if a fault occurred, output error info
if (isset($fault)) {
        print "Error: ". $fault;
        }
else if ($price == -1) {
        print "The book is not in the database.";
} else {
        // otherwise output the result
        print "The price of book number ". $param[isbn] ." is $". $price;
        }
// kill object
unset($client);
?>

76
задан brian d foy 26 September 2009 в 19:11
поделиться

8 ответов

Вы часто видите проверку на определенность, поэтому вам не нужно иметь дело с предупреждением об использовании значения undef (а в Perl 5.10 он сообщает вам ошибочную переменную):

 Use of uninitialized value $name in ...

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

 {
 no warnings 'uninitialized';

 if( length $name ) {
      ...
      }
 }

В других случаях используйте какое-то нулевое значение вместо данных. С помощью оператора defined-or Perl 5.10 вы можете указать length явную пустую строку (определенную и вернуть нулевую длину) вместо переменной, которая вызовет предупреждение:

 use 5.010;

 if( length( $name // '' ) ) {
      ...
      }

В Perl 5.12 это ' немного проще, потому что length для неопределенного значения также возвращает undefined . Это может показаться немного глупым, но это нравится математику, которым я, возможно, хотел бы быть. Это не вызывает предупреждения, поэтому этот вопрос существует.

use 5.012;
use warnings;

my $name;

if( length $name ) { # no warning
    ...
    }
72
ответ дан 24 November 2019 в 11:20
поделиться

Во-первых, поскольку length всегда возвращает неотрицательное число,

if ( length $name )

и

if ( length $name > 0 )

эквивалентны.

Если вы согласны с заменой неопределенного значения пустой строкой, вы можете использовать оператор Perl 5.10 // = , который присваивает правую часть левой, если не определена левая:

#!/usr/bin/perl

use feature qw( say );
use strict; use warnings;

my $name;

say 'nonempty' if length($name //= '');
say "'$name'";

Обратите внимание на отсутствие предупреждений о неинициализированной переменной, поскольку $ name присваивается пустая строка, если она не определена.

Однако, если вы не хотите зависеть от установки 5.10, используйте функции, предоставляемые Scalar :: MoreUtils . Например, приведенное выше может быть записано как:

#!/usr/bin/perl

use strict; use warnings;

use Scalar::MoreUtils qw( define );

my $name;

print "nonempty\n" if length($name = define $name);
print "'$name'\n";

Если вы не хотите тупить $ name , используйте по умолчанию .

15
ответ дан 24 November 2019 в 11:20
поделиться

Вы могли бы сказать

 $name ne ""

вместо

 length $name > 0
1
ответ дан 24 November 2019 в 11:20
поделиться

В случаях, когда я не Меня не волнует, является ли переменная undef или равна '' , я обычно резюмирую ее как:

$name = "" unless defined $name;
if($name ne '') {
  # do something with $name
}
6
ответ дан 24 November 2019 в 11:20
поделиться

Не всегда возможно делать повторяющиеся вещи простым и элегантным способом.

Просто делайте то, что вы всегда делаете, когда у вас есть общий код, который копируется во многих проектах:

Выполните поиск по CPAN, возможно, у кого-то уже есть код для вас. Для этой проблемы я нашел Scalar :: MoreUtils .

Если вы не найдете что-то, что вам нравится на CPAN, создайте модуль и поместите код в подпрограмму:

package My::String::Util;
use strict;
use warnings;
our @ISA = qw( Exporter );
our @EXPORT = ();
our @EXPORT_OK = qw( is_nonempty);

use Carp  qw(croak);

sub is_nonempty ($) {
    croak "is_nonempty() requires an argument" 
        unless @_ == 1;

    no warnings 'uninitialized';

    return( defined $_[0] and length $_[0] != 0 );
}

1;

=head1 BOILERPLATE POD

blah blah blah

=head3 is_nonempty

Returns true if the argument is defined and has non-zero length.    

More boilerplate POD.

=cut

Затем в коде вызовите it:

use My::String::Util qw( is_nonempty );

if ( is_nonempty $name ) {
    # do something with $name
}

Или, если вы возражаете против прототипов и не возражаете против дополнительных скобок, пропустите прототип в модуле и назовите его так: is_nonempty ($ name) .

1
ответ дан 24 November 2019 в 11:20
поделиться

Как насчет

if (length ($name || '')) {
  # do something with $name
}

Это не совсем эквивалент вашей исходной версии, так как он также вернет false, если $ name будет числовое значение 0 или строка '0' , но будет вести себя одинаково во всех других случаях.

В Perl 5.10 (или новее) подходящим подходом было бы использование оператора defined-or вместо этого:

use feature ':5.10';
if (length ($name // '')) {
  # do something with $name
}

Это будет решать, какую длину получить, в зависимости от того, определено ли $ name , а не от того, истинно ли оно, поэтому 0 / '0' будет обрабатывать эти случаи правильно, но для этого требуется более свежая версия perl, чем есть у многих.

-2
ответ дан 24 November 2019 в 11:20
поделиться

Как указывает мобрул, вы можете использовать вместо этого для небольшой экономии:

if (defined $name && $name ne '') {
    # do something with $name
}

Вы можете отказаться от определенной проверки и получить что-то еще более короткое, например:

if ($name ne '') {
    # do something with $name
}

Но в случае, когда $ name не определено, хотя логический поток будет работать так, как задумано, если вы используете предупреждения (а вы должны использовать), то вы получите следующее предупреждение:

Use of uninitialized value in string ne

Итак, если есть вероятность, что $ name не может быть определено, вам действительно нужно в первую очередь проверить определенность, чтобы избежать этого предупреждения. Как указывает Синан Унюр, вы можете использовать Scalar :: MoreUtils , чтобы получить код, который делает именно это (проверяет определенность, затем проверяет нулевую длину) из коробки, с помощью empty () метод:

use Scalar::MoreUtils qw(empty);
if(not empty($name)) {
    # do something with $name 
}
23
ответ дан 24 November 2019 в 11:20
поделиться
if ($name )
{
    #since undef and '' both evaluate to false 
    #this should work only when string is defined and non-empty...
    #unless you're expecting someting like $name="0" which is false.
    #notice though that $name="00" is not false
}
-3
ответ дан 24 November 2019 в 11:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: