Либо преобразуйте глобус в регулярное выражение, либо используйте Perl для обработки шаблонов глобуса - PullRequest
3 голосов
/ 07 июля 2011

У меня есть файл config .ini, где пользователи могут указывать шаблон файла, используя регулярное выражение Perl или как шаблон глобинга Ant. Например, следующее запрещает пользователю создавать файлы, которые не разрешены в Windows:

[BAN Defined using Ant Globbing]
file = **/prn.*
ignorecase = true

[BAN Defined using Regular expressions]
match = /(aux|con|com[0-9]*|lpt[0-9]*|nul|clock$)\.?[a-z]$
ignorecase = true

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

  • Простой способ преобразования глобуса в регулярное выражение
  • Методы сопоставления глобальных выражений, как вы можете с регулярными выражениями.

Например:

 if ($regex =~ /\/(aux|con|com[0-9]*|lpt[0-9]*|nul|clock$)\.?[a-z]$) {
 if ($glob ?magic? /**/prn.*/) {

Я надеялся, что есть какой-то волшебный способ сделать это на Perl. Итак, есть ли простой способ пропустить это:

Кстати, вот моя подпрограмма на случай, если кому-то будет интересно:

sub glob2regex {
    my $glob = shift;

    my $regex = undef;
    my $previousAstrisk = undef;

    foreach my $letter (split(//, $glob)) {
        #
        #    ####Check if previous letter was astrisk
        #
        if ($previousAstrisk) {
            if ($letter eq "*") { #Double astrisk
                $regex .= ".*";
                $previousAstrisk = undef;
                next;
            } else {        #Single astrisk: Write prev match
                $regex .= "[^/]*";
                $previousAstrisk = undef;
            }
        }
        #
        #   ####Quote all Regex characters w/ no meaning in glob
        #
        if ($letter =~ /[\{\}\.\+\(\)\[\]]/) {
            $regex .= "\\$letter";
            #
            #   ####Translate "?" to Regular expression equivelent
            #
        } elsif ($letter eq "?") {
            $regex .= ".";
            #
            #   ####Don't know how to handle astrisks until  the next line
            #
        } elsif ($letter eq "*") {
            $previousAstrisk = 1;
            #
            #   ####Convert backslashes to forward slashes
            #
        } elsif ($letter eq '\\') {
            $regex .= "/";
            #
            #   ####Just a letter
            #
        } else {
            $regex .= $letter;
        }
    }
    #
    #   ####Handle if last letter was astrisk
    #
    if ($previousAstrisk) {
        $regex .= "[^/]*";
    }
    #
    #    ####Globs are anchored to both beginning and ending
    #
    $regex = "^$regex\$";
    return $regex;
}

Ответы [ 2 ]

2 голосов
/ 12 февраля 2013

Учитывая, что:

  1. ?соответствует ровно одному символу, кроме '/'
  2. * соответствует нулю или более символов, кроме '/'
  3. ** соответствует всему, включая /

Если вы этого не сделаетепозаботьтесь о проверке формата и некоторых угловых случаях, таких как '***', тогда может работать следующая стратегия, в которой вы сначала конвертируете специальные символы в специально разработанные escape-последовательности, а затем конвертируете escape-последовательности в конечные строки:

my $rgx="^$glob\$";
$rgx=~ s|!|!e|g;
$rgx=~ s|[+]|!p|g;
$rgx=~ s|[*]{2}|!d|g;
$rgx=~ s|[*]|!s|g;
$rgx=~ s|[?]|!q|g;
$rgx=~ s|[.]|\\.|g;

$rgx=~ s|!d|.*|g;
$rgx=~ s|!s|[^/]*|g;
$rgx=~ s|!q|[^/]|g;
$rgx=~ s|!p|\\+|g;
$rgx=~ s|!e|!|g;
if ($path =~ m|$rgx|){
    return 1;
}
1 голос
/ 05 августа 2011

По-видимому, нет хитрого трюка Perl Guru для создания регулярного выражения из глобуса.Drats.

Лучшее, что я могу сделать, - это найти модуль CPAN, такой как Text :: Glob , который это делает.Тем не менее, Text::Glob не выполняет расширенную глобализацию в стиле Ant , поэтому мне все равно придется ее изменить.И код не проще, чем у меня уже есть.

Итак, я просто придерживаюсь того, что имею.

В любом случае, спасибо.

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