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

прочитав несколько вопросов и ответов за последние несколько недель, я видел использование d в Perl регулярные выражения прокомментированы как неправильные. Как и в более поздних версиях Perl d это не то же самое как [0-9], as d будет представлять любой символ Юникода, который имеет атрибут 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

8 ответов


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

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

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

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

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


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

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

  • если я правильно прочитал диаграммы unicode'۷۰ ' - это число (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��
    

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


по данным perlreref, '\d ' -это языковой стандарт и Unicode.

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

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


так же, как взорвать сайт с орбиты,[0-9] - это единственный способ быть уверенным. Да, это уродливо. Да, выбор сделать \d быть UNICODE и locale aware было глупо. Но это наша кровать и мы должны лежать в ней.

что касается людей, ныряющих головой в песок, говоря, что это не влияет на набор символов, который они используют сегодня, ну, вы можете использовать этот набор символов сегодня, но остальной мир использует 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 не обрабатывает все цифровые символы правильно. Я пишу модуль это сработает.


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


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

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


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


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

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

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

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