it-swarm.com.ru

Должен ли я использовать\d или [0-9] для сопоставления цифр в регулярном выражении Perl?

Прочитав несколько вопросов/ответов за последние несколько недель, я увидел использование \d в регулярных выражениях Perl, прокомментированных как неправильные. Так как в более поздних версиях Perl \d отличается от [0-9], \d будет представлять любой символ Unicode с атрибутом digit, а [0-9] представляет символы «0», «1», «2», ..., '9'.

Я ценю то, что в некоторых контекстах [0-9] будет правильным, а в других \d. Мне было интересно, какие люди считают правильным использовать по умолчанию?

Лично я считаю нотацию \d очень сжатой и выразительной, тогда как в сравнении [0-9] несколько громоздка. Но у меня мало опыта в написании многоязычного кода, точнее, кода для языков, которые не вписываются в диапазон символов ASCII и, следовательно, могут быть наивными.

Я заметил

$find /System/Library/Perl/5.8.8/ -name \*pm | xargs grep '\\d' | wc -l
  298
$find /System/Library/Perl/5.8.8/ -name \*pm | xargs grep '\[0-9\]' | wc -l
  26
45
Beano

Для максимальной безопасности я рекомендую использовать [0-9] в любое время, когда вы не собираетесь специально сопоставлять все определяемые юникодом цифры.

Per perldoc perluniintro , Perl не поддерживает использование цифр, отличных от [0-9], в качестве чисел, поэтому я бы определенно использовал [0-9], если выполняются следующие условия:

  1. Вы хотите использовать результат как число (например, выполнять математические операции с ним или хранить его где-то, что принимает только правильные числа (например, столбец INT в базе данных)).

  2. Возможно, в данных будут присутствовать нецифровые символы [^0-9] таким образом, чтобы регулярное выражение могло им соответствовать. (Обратите внимание, что этот параметр всегда следует считать верным для ненадежного/враждебного ввода.)

Если любое из этих значений является ложным, то редко будет причина специально not использовать \d (и вы, вероятно, сможете сказать, когда это так), и если вы пытаетесь сопоставляя все определяемые юникодом цифры, вы определенно захотите использовать \d.

38
Nicholas Knight

Мне кажется очень опасным использовать \d. Это плохое дизайнерское решение на языке, так как в большинстве случаев вам нужен [0-9]. Кодирование Хаффмана будет диктовать использование \d для чисел ASCII. 

Большинство предыдущих постеров уже подчеркивали, почему вы должны использовать [0-9], поэтому позвольте мне дать вам немного больше данных: 

  • Если я правильно читаю графики Юникода, «۷۰» - это число (70 знаков, не берите мое Слово за это).

  • Попробуй это: 

    $ Perl -le '$one = chr 0xFF11; print "$one + 1 = ", $one+1;'
    1 + 1 = 1
    
  • Вот неполный список действительных чисел (которые могут отображаться или не отображаться в вашем браузере должным образом, в зависимости от используемых вами шрифтов), для каждого числа только первый из тех, которые интерпретируются как число при выполнении арифметики с Perl, как показано выше:

     ZERO:  0٠۰߀०০੦૦୦௦౦೦൦๐໐0
     ONE:   1١۱߁१১੧૧୧௧౧೧൧๑໑1
     TWO:   2٢۲߂२২੨૨୨௨౨೨൨๒໒2
     THREE: 3٣۳߃३৩੩૩୩௩౩೩൩๓໓3
     FOUR:  4٤۴߄४৪੪૪୪௪౪೪൪๔໔4
     FIVE:  5٥۵߅५৫੫૫୫௫౫೫൫๕໕5
     SIX:   6٦۶߆६৬੬૬୬௬౬೬൬๖໖6
     SEVEN: 7٧۷߇७৭੭૭୭௭౭೭൭๗໗7
     EIGHT: 8٨۸߈८৮੮૮୮௮౮೮൮๘໘8
     NINE:  9٩۹߉९৯੯૯୯௯౯೯൯๙໙9��
    

Вы все еще не убеждены?

52
mirod

Согласно perlreref , '\d' поддерживает локальные настройки и Unicode.

Однако, если используемый вами кодовый набор не является Unicode, вам не нужно беспокоиться о цифрах Unicode, и если используемый вами кодовый набор похож на Latin-1 (ISO 8859-1 или 8859-15), тогда знание языка также не повредит вам, потому что кодовый набор не содержит никаких других цифровых символов.

Таким образом, для многих людей большую часть времени вы можете использовать \d без каких-либо проблем. Однако, если данные Unicode являются частью вашей работы, вам необходимо более тщательно продумать, что вам нужно.

8
Jonathan Leffler

Так же, как взломать сайт с орбиты, [0-9] - единственный способ быть уверенным. Да, это ужасно Да, выбор сделать \d УНИКАЛЬНЫМ и с учетом региональных особенностей был глупым. Но это наша кровать, и мы должны лежать в ней.

Что касается людей, уклоняющихся головой в песок, говорящих, что это не влияет на набор символов, который они используют сегодня, хорошо, вы можете использовать этот набор символов сегодня, но остальной мир использует UTF-8 сейчас, и вы будете используя это скоро также. Не забывайте кодировать, как парень, который поддерживает ваш код, - маньяк-убийца, который знает, где вы живете.

Да, и что касается модулей Perl, использующих \d vs [0-9], даже ядро ​​все еще имеет проблемы с UNICODE .

Если вы на самом деле имеете в виду любую цифру, но хотите иметь возможность вычислять результаты, вы можете использовать Text::Unidecode :

#!/usr/bin/Perl

use strict;
use warnings;

use Text::Unidecode;

my $number = "\x{1811}\x{1812}\x{1813}\x{1814}\x{1815}";
print "$number is ", unidecode($number), "\n";

После еще одного тестирования это выглядит так: Text :: Unidecode не обрабатывает все цифровые символы правильно. Я пишу модуль это будет работать.

5
Chas. Owens

Я чувствую, что оба должны иметь свое место. Тем не менее, 99,999% времени (особенно в моем закрытом большом американском мире сотрудничества) они взаимозаменяемы. Я использую Perl для манипулирования данными каждый день, и ни в одном из наборов данных, с которыми я имею дело, нет чисел, которые не вписываются в [0-9]. Тем не менее, я ценю, что есть важное различие между \d и [0-9], и хорошо знать об этой разнице. Я использую \d, потому что он кажется более лаконичным (как вы сказали) и никогда не будет «неправильным» в моем маленьком мире манипулирования данными.

3
Copas

Если вы примените \d к строке Unicode (например, в "\X{660}" =~ /\d/), она будет соответствовать цифре Unicode. Если вы примените \d к двоичной строке (такой как UTF-8, эквивалентный приведенному выше: "\xd9\xa0" =~ /\d/), она будет соответствовать только 10 ASCII цифрам. Perl 5.8 не создает строки Unicode по умолчанию (если только вы не попросите об этом, например, в "\X{...}" или use utf8; и т.д.).

Поэтому мой совет: обращайте внимание только на разницу между \d и [0-9], если ваше приложение использует строки Unicode.

2
pts

Если [0-9] чувствует себя неуклюже, возможно, вы могли бы определить: $d=qr/[0-9]/; и использовать это вместо \d.

1
Mattias

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

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

 'ip\haddress\h(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\D'

Если, с другой стороны, вы пытаетесь найти IP-адрес, встроенный где-то глубоко, скажем, в X-заголовок электронной почты, или если вы пытаетесь проверить IP-адрес, ну ... это целая другая история!

0
skeetastax