Как я создаю регулярные выражения Perl динамично?

Отчасти это будет зависеть от вашего знакомства с Objective-C и его API.

Сказав это, книга Hilleglass Cocoa и книга Дейва Марка оба превосходны (особенно книга Дэйва Марка). Я еще не читал книгу «Ранчо большого ботаника», но эти двое - «должны иметь». Книга Дейва Марка опускает все остальные книги по программированию для iPhone.

В дополнение к тем, которые вы, вероятно, хотите подробно рассмотреть «Шаблоны проектирования какао» Эрика Бака и «Программирование в Objective-C 2.0» Стивена Кочана. API-интерфейсы Cocoa находятся под сильным влиянием шаблонов проектирования, и понимание того, как их использовать, а также семантики языка будет иметь большое значение.

Возможно, вы захотите добавить пару конкретных книг по некоторым API-интерфейсам Cocoa, в частности, по Core Data и Core Animation. Очень хорошее понимание базовых данных навсегда изменит ваши возможности кодирования. Лучшая книга на эту тему - «Прагматическая» Маркуса Зарры.

Наличие более пары книг - это всегда хорошо ...; -)

8
задан Michael Myers 22 May 2009 в 16:07
поделиться

6 ответов

Предполагая, что вы проанализировали файл конфигурации, чтобы получить список расширений и игнорируемых каталогов, вы можете построить регулярное выражение в виде строки, а затем использовать оператор qr чтобы скомпилировать его в регулярное выражение:

my @extensions = qw(avi flv mp3 mp4 wmv);  # parsed from file
my $pattern    = '\.(' . join('|', @wanted) . ')$';
my $regex      = qr/$pattern/;

if ($file =~ $regex) {
    # do something
}

Компиляция не является строго необходимой; вы можете использовать строковый шаблон напрямую:

if ($file =~ /$pattern/) {
    # do something
}

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

%ignore = ('.svn' => 1);

Каталоги с суффиксами могут быть созданы так же, как и расширения файлов:

my $dir_pattern = '(?:' . join('|', map {quotemeta} @dir_suffix), ')$';
my $dir_regex   = qr/$dir_pattern/;

Вы даже можете встроить шаблоны в анонимные подпрограммы, чтобы избежать ссылок на глобальные переменные:

my $file_filter    = sub { $_ =~ $regex };
my $descend_filter = sub {
    ! $ignore{$File::Next::dir} &&
    ! $File::Next::dir =~ $dir_regex;
};

my $iter = File::Next::files({
    file_filter    => $file_filter,
    descend_filter => $descend_filter,
}, $directory);
26
ответ дан 5 December 2019 в 05:08
поделиться

Допустим, вы используете Config :: General для своего конфигурационного файла и что он содержит следующие строки:

<MyApp>
    extensions    avi flv mp3 mp4 wmv
    unwanted      frames svn
</MyApp>

Затем вы можете использовать его так (см. Config :: General для получения дополнительной информации):

my $conf = Config::General->new('/path/to/myapp.conf')->getall();
my $extension_string = $conf{'MyApp'}{'extensions'};

my @extensions = split m{ }, $extension_string;

# Some sanity checks maybe...

my $regex_builder = join '|', @extensions;

$regex_builder = '.(' . $regex_builder . ')$';

my $regex = qr/$regex_builder/;

if($file =~ m{$regex}) {
    # Do something.
}


my $uw_regex_builder = '.(' . join ('|', split (m{ }, $conf{'MyApp'}{'unwanted'})) . ')$';
my $unwanted_regex = qr/$uw_regex_builder/;

if(File::Next::dir !~ m{$unwanted_regex}) {
    # Do something. (Note that this does not enforce /^.svn$/. You
    # will need some kind of agreed syntax in your conf-file for that.
}

(Это полностью не проверено.)

3
ответ дан 5 December 2019 в 05:08
поделиться

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

#!/usr/bin/perl

use strict;
use warnings;

my (@ext, $dir, $dirp);
while (<DATA>) {
    next unless my ($key, $val) = /^ \s* (ext|dirp|dir) \s* = \s* (\S+)$/x;
    push @ext, $val if $key eq 'ext';
    $dir = $val     if $key eq 'dir';
    $dirp = $val    if $key eq 'dirp';
}

my $re = join "|", @ext;
$re = qr/[.]($re)$/;

print "$re\n";

while (<>) {
    print /$re/ ? "matched" : "didn't match", "\n";
}

__DATA__
ext = avi
ext = flv
ext = mp3
dir = .svn
dirp= .frames
3
ответ дан 5 December 2019 в 05:08
поделиться

Достаточно просто с File :: Find :: Rule, просто случай создания списка заранее.

use strict;
use warnings;
use aliased 'File::Find::Rule';


# name can do both styles. 
my @ignoredDirs = (qr/^.svn/,  '*.frames' );
my @wantExt = qw( *.avi *.flv *.mp3 );

my $finder = Rule->or( 
    Rule->new->directory->name(@ignoredDirs)->prune->discard, 
    Rule->new->file->name(@wantExt)
);

$finder->start('./');

while( my $file = $finder->match() ){
    # Matching file.
}

Тогда это просто случай заполнения этих массивов. (Примечание: приведенный выше код также не протестирован, но, вероятно, будет работать). Я обычно использую для этого YAML, это облегчает жизнь.

use strict;
use warnings;
use aliased 'File::Find::Rule';
use YAML::XS;

my $config = YAML::XS::Load(<<'EOF');
---
ignoredir:
- !!perl/regexp (?-xism:^.svn)
- '*.frames'
want:
- '*.avi'
- '*.flv'
- '*.mp3'
EOF

my $finder = Rule->or( 
    Rule->new->directory->name(@{ $config->{ignoredir} })->prune->discard, 
    Rule->new->file->name(@{ $config->{want} })
);

$finder->start('./');

while( my $file = $finder->match() ){
    # Matching file.
}

Примечание Использование удобного модуля aliased.pm, который импортирует "File :: Find :: Rule" для меня как "Rule".

1
ответ дан 5 December 2019 в 05:08
поделиться

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

use strict;
use Regexp::Assemble;

my $re = Regexp::Assemble->new->add(qw(avi flv mp3 mp4 wmv));

...

if ($file =~ /$re/) {
    # a match!
}

print "$re\n"; # (?:(?:fl|wm)v|mp[34]|avi)
1
ответ дан 5 December 2019 в 05:08
поделиться

Хотя File :: Find :: Rule уже имеет способы справиться с этим, в подобных случаях вам действительно не нужно регулярное выражение. Регулярное выражение здесь не очень выгодно, потому что вы ищете фиксированную последовательность символов в конце каждого имени файла. Вы хотите знать, входит ли эта фиксированная последовательность в список интересующих вас последовательностей. Сохраните все расширения в хеше и посмотрите в него:

my( $extension ) = $filename =~ m/\.([^.]+)$/;
if( exists $hash{$extension} ) { ... }

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

0
ответ дан 5 December 2019 в 05:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: