perl中的字符串掩码,用于了解格式变化

时间:2014-01-27 16:30:34

标签: regex perl

我正在尝试从逻辑方式组织但具有可选部分的文件夹列表中提取信息。

下面是我的文件夹结构,其中包含可选字段<> :

artist - album_nr. album_title <(type)> <(issue_info)> (year) [quality]

所以一些目录的例子会像这样命名

Emperor - 03. Reverence (EP) (1997) [flac]
Emperor - 05b. IX Equilibrium (reissue 2007) (1999) [cue-flac]
Exodus - 01a. Bonded    By Blood (1985) [cue-flac]
Exodus - 01b. Bonded By Blood    (remaster 2008) (1985) [cue-flac]
Exodus - 03.Tempo of the Damned    (EP) (remaster 2008) (1985) [cue-flac]

我需要一个正则表达式,它会正确地将相关部分拉入数组以进行进一步处理但是很难,主要是因为可选字段。

最多,该数组至少包含7条信息和5条信息。

如果有人能帮助我,我将非常感激,这将为我节省大量的手工工作。

1 个答案:

答案 0 :(得分:1)

使用扩展符号表示易读性:

my $re = qr/
    ([^-]+?)          # artist
    \h*               # 
    -                 # literal '-'
    \h*               # 
    ([0-9]+[a-z]?)    # album number
    \.                # literal '.'
    \h*               # 
    ([^(]+?)          # album title
    \h*               # 
    (?:\(([^)]+)\))?  # type (optional)
    \h*               # 
    (?:\(([^)]+)\))?  # issue info (optional)
    \h*               # 
    \(([^)]+)\)       # year
    \h*               # 
    \[(.+)\]          # quality
/x;

请注意,此正则表达式始终返回七个值(匹配时),因为有七个捕获。

你说你遇到麻烦的可选部分的“技巧”是 在捕获,非捕获和字面括号中导航。正则表达式的那些部分分解如下:

(?:    # begin non-capturing grouping (for '?' quantifier at the end)
\(     # literal '('
(      # begin capture
[^)]+  # any character other than ')', one or more times
)      # end capture
\)     # literal ')'
)      # end non-capturing grouping
?      # zero or one quantifier (make everything in group optional)

编辑:在评论中,Jerry正确地指出,当数据中只有一个可选字段(类型或问题信息)时,匹配的内容可能存在歧义。这可以通过使正则表达式更不容许(存在未能匹配某些数据的风险 - 始终检查匹配是否成功)来解决。这适用于您提供的示例数据:

(?:\((\w+\h+[0-9]{4}+)\))? # issue info (optional)

如果我们这样做,那么使年份也更具限制性似乎也是谨慎的。

\(([0-9]{4})\) # year