Регулярное выражение для соответствия только первому файлу в наборе файлов RAR - PullRequest
1 голос
/ 21 сентября 2008

Чтобы увидеть, какой файл вызывать команду unrar, нужно определить, какой файл является первым в наборе файлов.

Вот несколько примеров имен файлов, из которых - естественно - должна соответствовать только первая группа:

yes.rar
yes.part1.rar
yes.part01.rar
yes.part001.rar

no.part2.rar
no.part02.rar
no.part002.rar
no.part011.rar

Один (ограниченный) способ сделать это с помощью регулярных выражений, совместимых с PCRE, таков:

.*(?:(?<!part\d\d\d|part\d\d|\d)\.rar|\.part0*1\.rar)

Это не сработало в Ruby, когда я тестировал его на Rejax однако.

Как бы вы написали одно Ruby-совместимое регулярное выражение для соответствия только первому файлу в наборе файлов RAR?

Ответы [ 4 ]

4 голосов
/ 29 марта 2010

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

Заголовки RAR сообщат вам, какой файл является первым в томе, при условии, что они были созданы в несколько более поздней версии RAR.

HEAD_FLAGS Битовые флаги:
2 байта

0x0100 - Первый том (устанавливается только RAR 3.0 и выше)

Итак, откройте каждый файл и изучите заголовки RAR, специально ища флаг, указывающий, какой файл является первым томом. Это никогда не подведет, пока архив не поврежден. Я провел свои собственные тесты с охватывающими архивами RAR, и их заголовки верны по ссылке выше.

Это гораздо более безопасный способ определить, какой файл находится первым в наборе, подобном этому.

3 голосов
/ 21 сентября 2008

Короткий ответ: невозможно создать одно регулярное выражение для решения вашей проблемы. Ruby 1.8 не имеет обходных утверждений ((?

1) Используйте более одного регулярного выражения, чтобы сделать это.

def is_first_rar(filename)
    if ((filename =~ /part(\d+)\.rar$/) == nil)
        return (filename =~ /\.rar$/) != nil
    else
        return $1.to_i == 1
    end
end

2) Используйте regex engine для ruby ​​1.9, Oniguruma . Он поддерживает косвенные утверждения, и вы можете установить его как гем для ruby ​​1.8 . После этого вы можете сделать что-то вроде этого:

def is_first_rar(filename)
    reg = Oniguruma::ORegexp.new('.*(?:(?<!part\d\d\d|part\d\d|\d)\.rar|\.part0*1\.rar)')
    match = reg.match(filename)
    return match != nil
end
0 голосов
/ 21 сентября 2008

Лично я бы не использовал (расширенные) регулярные выражения в этом случае (или, по крайней мере, не одно, чтобы сделать все это). Что не так с кодированием, например, в нескольких if с?

0 голосов
/ 21 сентября 2008

Я не эксперт по регулярным выражениям, но вот моя попытка

^(yes|no)\.(rar|part0*1\.rar)$

Заменить «да | нет» на фактическое имя файла. Я сопоставил его с вашими примерами, чтобы увидеть, будет ли он соответствовать только первому набору, поэтому в регулярном выражении указано «да | нет».

ОБНОВЛЕНИЕ: исправлено согласно комментарию. Не уверен, почему пользователь не знает имя файла, поэтому я не исправил эту часть ...

...