2016-02-02 3 views
2

Я нашел это при изучении некоторого рабочего кода. Также в кодировке perl я все еще новичок. Вот мой вопрос: Каковы различия между этим условием IF?Различия в том случае, если условие

if ($command =~ /send|regd|succ|fail|recv/) 

и этот

if (($command == "send") || ($command == "regd") || ($command == "succ") 
    || ($command == "fail") || ($command == "recv")) 
+4

Второй оператор 'if' использует числовые оператор равенства '==' для проверки строк. Это должно быть 'eq', оператор равенства строк. – mttrb

+1

Первый будет соответствовать слишком много - любая строка с send, regd и т. Д. В них. –

ответ

5

Прежде всего, как упоминалось комментатора, == делает числовое сравнение. если строка не похожа на число, ее числовое значение равно 0, поэтому вполне вероятно, что команда $ будет казаться равной всем этим строкам, если используется ==. Правильный способ сравнения строк - с eq, например, if ($command eq "send").

Даже с правильным оператором равенства все еще существует разница. Первая версия использует совпадение с шаблоном, и шаблон не привязан, поэтому он может совпадать в любом месте строки. Например, если $command является «blahblahsendxxxxxx», то $command =~ /send/ является истинным. Вы можете привязать шаблон, чтобы убедиться, что он соответствует всей строке, поместив a в начале и $ в конец.

+0

Благодарим вас за ответ и за простое объяснение. :) –

1

Как упоминал Энди, вам нужно использовать eq, а не ==, и он должен привязать ваше регулярное выражение. В этом случае вам также не нужно обертывать все условия в цепочке ||.

Есть 2 «отличия», о которых я могу думать: производительность и читаемость. «||» цепочка более совершенна, но только немного. Если вы добавили больше терминов, регулярное выражение в конечном итоге побьет его. Регулярное выражение, вероятно, более читаемо, и его легче расширять и модифицировать.

Вот Тест, который я использовал для проверки производительности.

use Benchmark 'cmpthese'; 

my $cmd = 'recv'; 

cmpthese(-1, { 
    REG => sub { 
     if ($cmd =~ /^(?:send|regd|succ|fail|recv)$/) { 
      return 1; 
     } 
    }, 
    OR => sub { 
     if ($cmd eq 'send'||$cmd eq 'regd'||$cmd eq 'succ'||$cmd eq 'fail'||$cmd eq 'recv') { 
      return 1; 
     } 
    }, 
}); 

Я проверка recv, как это последний в цепочке должно быть медленным, чтобы пройти.

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

my %valid = map { $_ => 1 } qw(send regd succ fail recv); 
# Later ... 
if ($valid{$cmd}) { return 1; } 
+1

Сравнение ухудшается, если указанное имя не соответствует (поэтому одно из слов, переданных в тест, - «катаклизм» или «тектонический» или что-то еще). Затем он должен делать больше работы каждый раз, чтобы установить, что он не соответствует, тогда как регулярное выражение обнаруживает несоответствие намного быстрее.Слово, такое как 'failure' или' success', заставит регулярное выражение работать немного больше (ему нужно будет обрабатывать 4 символа вместо 1), но это все же быстрее, чем увеличивается количество альтернатив. –

+0

@ Joshua Я благодарен за ваш ответ между Performance и Readability. Я буду учитывать это, когда буду кодировать в будущем. TQSM. Приветствия. –

0

Объяснение первое условие: строка «команда $» совпадает с любым из текста/части текста со значением «отправить» или «Regd» или «Succ» или «провал» или «RECV» независимо от положения.

Пояснение для второго условия: Второй синтаксис кода должен был быть if ($ command eq "send" || $ команда eq "regd" || $ команда eq "succ" || $ команда eq "fail" || $ command eq "recv") вместо указанного выше. В отличие от первого условия, во втором условии строка $ command должна точно соответствовать тексту «send» или «regd» или «succ» или «fail» или «recv»

Смежные вопросы