Как сделать параметры Perl Regex условными - PullRequest
1 голос
/ 28 февраля 2011

НЕ ЗАПРОСИТЕ ПОЧЕМУ, но ...

У меня есть регулярное выражение, которое должно быть без учета регистра при запуске в Windows, НО чувствительно к регистру при запуске в * nix.

Вотпример фрагмента того, что я сейчас вроде как делаю.

sub relative_path 
{
    my ($root, $path) = @_;

    if ($os eq "windows")
    {
        # case insensitive with regex option 'i'
        if ($path !~ /^\Q$root\E[\\\/](.*)$/i)
        {
            print "\tFAIL:$root not in $path\n";
        }
        else
        {
            return $1;
        }
    }
    else
    {
        # case sensitive
        if ($path !~ /^\Q$root\E[\\\/](.*)$/)
        {
            print "\tFAIL:$root not in $path\n";
        }
        else
        {
            return $1;
        }
    }
    return "";
}

Аааа!Повторение вредит моему ОКР, но мое перл-фу слабое.Каким-то образом я хочу сделать условие регулярного выражения 'i' условным регистром без учета регистра, но не знаю как?

Ответы [ 4 ]

9 голосов
/ 28 февраля 2011

Вы можете использовать расширенную конструкцию, чтобы указать опцию.Например:

#!/usr/bin/env perl

use warnings; use strict;

my $s = 'S';

print check($s, 'i'), "\n";
print check($s, '-i'), "\n";

sub check {
    my ($s, $opt) = @_;
    return "Matched" if $s =~ /(?$opt)^s\z/;
    return "Did not match";
}

См. perldoc perlre .

5 голосов
/ 28 февраля 2011

Вы можете создавать шаблоны и сохранять их в скалярах, используя оператор qr:

sub relative_path 
{
    my ($root, $path) = @_;

    my $pattern = ($os eq "windows") ? qr/^\Q$root\E[\\\/](.*)$/i : qr/^\Q$root\E[\\\/](.*)$/;

    if ($path !~ $pattern)
    {
        print "\tFAIL:$root not in $path\n";
    }
    else
    {
        return $1;
    }
}

Возможно, это не на 100% идеально, но, надеюсь, вам понравится идея.

Обязательно ознакомьтесь с разделом "Операторы цитирования и операторы, подобные цитате" в perlop .

<ч />

РЕДАКТИРОВАТЬ: Хорошо, вот СУХОЕ решение, так как люди жалуются на это.

sub relative_path 
{
    my ($root, $path) = @_;

    my $base_pattern = qr/^\Q$root\E[\\\/](.*)$/;
    my $pattern = ($os eq "windows") ? qr/$base_pattern/i : $base_pattern;

    if ($path !~ $pattern)
    {
        print "\tFAIL:$root not in $path\n";
    }
    else
    {
        return $1;
    }
}
4 голосов
/ 01 марта 2011

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

use Path::Class qw( dir );

sub relative_path {
   my ($root, $path) = @_;

   if ($^O =~ /Win32/) {
      require Win32;
      $root = Win32::GetLongPathName($root);
      $path = Win32::GetLongPathName($path);
   }

   $root = dir($root);
   $path = dir($path);

   if ($root->subsumes($path)) {
      return $path->relative($root);
   } else {
      print "\tFAIL:$root not in $path\n";
      return "";
   }
}

Кстати, не очень уместно обрабатывать ошибки там.Функция должна вернуть сигнал ошибки (вернуть undef, вызвать исключение и т. Д.), И вызывающая сторона должна обработать его так, как считает нужным.Разделение концернов.

1 голос
/ 01 марта 2011

Вы также можете сделать это, используя локальные модификаторы (опция расширенных регулярных выражений perl):

sub relative_path 
{
    my ($root, $path) = @_;

    my $pattern = "^\Q$root\E[\\\/](.*)$";
    $pattern = "(?i)$pattern" if ($os eq "windows");
    if ($path =~ /$pattern/)
    {
        return $1;
    }
    else
    {
        print "\tFAIL:$root not in $path\n";
    }
}

(после того, как я напечатал свой ответ, я увидел, что Синан также предложил его, но я также решил опубликовать свой ответ, поскольку он дает более конкретный ответ на вопрос)

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