正则表达式仅匹配RAR文件集中的第一个文件

时间:2020-03-06 14:29:51  来源:igfitidea点击:

要查看在哪个文件上调用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)

但是,当我在Rejax上对其进行测试时,这在Ruby中不起作用。

我们将如何编写一个与Ruby兼容的正则表达式以仅匹配一组RAR文件中的第一个文件?

解决方案

我不是正则表达式专家,但这是我的尝试

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

将" yes | no"替换为实际的文件名。我将其与示例进行了匹配,以查看它是否仅与第一组匹配,因此正则表达式中的"是|否"。

更新:根据注释进行修复。不知道为什么用户不知道文件名,所以我没有修复该部分。

就个人而言,在这种情况下,我不会使用(扩展的)正则表达式(或者至少不只使用一个正则表达式来完成所有操作)。例如,在几个ifs中进行编码有什么问题?

简短的答案是,不可能构造单个正则表达式来满足问题。 Ruby 1.8没有环视断言(示例正则表达式中的(?<!东西),这就是正则表达式不起作用的原因,这给我们留下了两个选择。

1)使用多个正则表达式来执行此操作。

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

2)将正则表达式引擎用于ruby 1.9 Oniguruma。它支持环视断言,我们可以将其安装为ruby 1.8的gem。之后,我们可以执行以下操作:

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

不要依靠文件名来确定哪个是第一个。我们最终将发现一个错误的情况,即我们得到了错误的文件。

RAR的标头会告诉我们哪个文件是卷中的第一个文件,假设它们是在RAR的最新版本中创建的。

HEAD_FLAGS      Bit flags:

  2 bytes  
  
  
    0x0100  - First volume (set only by RAR 3.0 and later)

因此,打开每个文件并检查RAR标头,专门寻找指示哪个文件是第一个卷的标志。只要档案没有损坏,它就永远不会失败。我已经使用跨RAR存档进行了自己的测试,并且根据上面的链接,其标头是正确的。

这样可以更安全地确定哪个文件是此类文件集中的首个文件。