我使用RubyZip从Ruby中的zip存档中提取文件,我需要根据文件名的特征标记文件:
实施例: 我有以下哈希:
labels = {
:data_file=>/.\.dat/i,
:metadata=>/.\.xml/i,
:text_location=>/.\.txt/i
}
所以,我在zip中有每个文件的文件名,让我们说一个例子是
filename = 382582941917841df.xml
假设每个文件只匹配labels
哈希中的一个正则表达式,如果不匹配则无关紧要,只需选择第一个匹配项即可。 (在这种情况下,正则表达式都用于检测扩展,但它可以检测任何文件名掩码,例如DSC ****。jpg。
我现在正在这样做:
label_match =~ labels.find {|key,value| filename =~ value}
---> label_match = [:metadata, /.\.xml/]
label_sym = label_match.nil? ? nil: label_match.first
所以这很好用,但看起来并不像Ruby那样。我有什么遗漏可以很好地清理它吗?
答案 0 :(得分:2)
case when
毫不费力地做到了这一点:
filename = "382582941917841df.xml"
category = case filename
when /.\.dat/i ; :data_file
when /.\.xml/i ; :metadata
when /.\.txt/i ; :text_location
end
p category # => :metadata ; nil if nothing matched
答案 1 :(得分:1)
我认为你正在倒退而且艰难。 Ruby可以轻松获取文件的扩展名,然后可以轻松地将其映射到某个文件。
从以下内容开始:
FILENAMES = %w[ foo.bar foo.baz 382582941917841df.xml DSC****.jpg]
FILETYPES = {
'.bar' => 'bar',
'.baz' => 'baz',
'.xml' => 'metadata',
'.dat' => 'data',
'.jpg' => 'image'
}
FILENAMES.each do |fn|
puts "#{ fn } is a #{ FILETYPES[File.extname(fn)] } file"
end
# >> foo.bar is a bar file
# >> foo.baz is a baz file
# >> 382582941917841df.xml is a metadata file
# >> DSC****.jpg is a image file
File.extname
内置于Ruby中。 File类包含许多类似的方法,可用于查找操作系统已知的文件和/或撕开文件路径和文件名,因此非常熟悉它是非常好的事情。
理解不正确编写的正则表达式(例如/.\.dat/i
)可能会导致很多痛苦,这一点也很重要。考虑这些:
'foo.xml.dat'[/.\.dat/] # => "l.dat"
'foo.database.20010101.csv'[/.\.dat/] # => "o.dat"
.
前面的字符重要或必要?extname
等方法更快,维护更少时,您是否真的希望使用无锚的正则表达式模式来降低代码速度?编写代码时需要考虑的事项。
答案 2 :(得分:0)
不要在没有匹配时使用nil
来指示标签,而是考虑使用其他符号,例如:unknown
。
然后你可以这样做:
labels = {
:data_file=>/.\.dat/i,
:metadata=>/.\.xml/i,
:text_location=>/.\.txt/i,
:unknown=>/.*/
}
label = labels.find {|key,value| filename =~ value}.first