我正在尝试从目录中的rar包中提取文件名。我正在使用返回多行字符串的7z,并希望在输出中搜索“mkv”,“avi”或“srt”文件。
这是我的代码:
ROOT_DIR = "/users/ken/extract"
# Check each directory for Rar packages
# Returns an arary of directories with filenames from the rar's
def checkdirs()
pkgdirs = {}
Dir.foreach(ROOT_DIR) do |d|
if !Dir.glob("#{ROOT_DIR}/#{d}/*.rar").empty?
rarlist = `7z l #{ROOT_DIR}/#{d}/*.rar`
puts rarlist # Returns multilinen output from 7z l
puts rarlist.scan('*.mkv').first
pkgdirs[d] = 'filename'
end
end
pkgdirs
end
我可以获得7z输出,但我无法弄清楚如何搜索输出中的字符串。如何搜索输出并返回匹配的行?
这是7z输出的一个例子:
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)
Scanning the drive for archives:
1 file, 15000000 bytes (15 MiB)
Listing archive: Gotham.S03E19.HDTV.x264-KILLERS/gotham.s03e19.hdtv.x264-killers.rar
--
Path = Gotham.S03E19.HDTV.x264-KILLERS/gotham.s03e19.hdtv.x264-killers.rar
Type = Rar
Physical Size = 15000000
Total Physical Size = 285988640
Characteristics = Volume FirstVolume VolCRC
Solid = -
Blocks = 1
Multivolume = +
Volume Index = 0
Volumes = 20
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2017-05-23 02:30:52 ..... 285986500 285986500 Gotham.S03E19.HDTV.x264-KILLERS.mkv
------------------- ----- ------------ ------------ ------------------------
2017-05-23 02:30:52 285986500 285986500 1 files
------------------- ----- ------------ ------------ ------------------------
2017-05-23 02:30:52 285986500 285986500 1 files
Archives: 1
Volumes: 20
Total archives size: 285988640
我期待这个输出:
2017-05-23 02:30:52 ..... 285986500 285986500 Gotham.S03E19.HDTV.x264-KILLERS.mkv
答案 0 :(得分:1)
您可以使用:
puts rarlist.scan(/^.*\.mkv/)
正则表达式将从行的开头匹配。
要匹配.mkv
,.avi
或.srt
,您可以使用:
rarlist.scan(/(^.*\.(mkv|avi|srt))/) {|a,_| puts a}
答案 1 :(得分:0)
解决方案比你制作的解决方案简单得多。
从:
开始TARGET_EXTENSIONS = %w[mkv avi srt]
TARGET_EXTENSION_RE = /\.(?:#{ Regexp.union(TARGET_EXTENSIONS).source})/
# => /\.(?:mkv|avi|srt)/
output = <<EOT
7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,8 CPUs x64)
Scanning the drive for archives:
1 file, 15000000 bytes (15 MiB)
Listing archive: Gotham.S03E19.HDTV.x264-KILLERS/gotham.s03e19.hdtv.x264-killers.rar
--
Path = Gotham.S03E19.HDTV.x264-KILLERS/gotham.s03e19.hdtv.x264-killers.rar
Type = Rar
Physical Size = 15000000
Total Physical Size = 285988640
Characteristics = Volume FirstVolume VolCRC
Solid = -
Blocks = 1
Multivolume = +
Volume Index = 0
Volumes = 20
Date Time Attr Size Compressed Name
------------------- ----- ------------ ------------ ------------------------
2017-05-23 02:30:52 ..... 285986500 285986500 Gotham.S03E19.HDTV.x264-KILLERS.mkv
------------------- ----- ------------ ------------ ------------------------
2017-05-23 02:30:52 285986500 285986500 1 files
------------------- ----- ------------ ------------ ------------------------
2017-05-23 02:30:52 285986500 285986500 1 files
Archives: 1
Volumes: 20
Total archives size: 285988640
EOT
只需迭代输出中的行和puts
匹配:
puts output.lines.grep(TARGET_EXTENSION_RE)
哪个会输出:
2017-05-23 02:30:52 ..... 285986500 285986500 Gotham.S03E19.HDTV.x264-KILLERS.mkv
以上是一个基本的解决方案,但根据收到的输出,有些事情可以加速代码:
TARGET_EXTENSIONS = %w[mkv avi srt].map { |e| '.' << e } # => [".mkv", ".avi", ".srt"]
puts output.split(/\r?\n/).select { |l| l.end_with?(*TARGET_EXTENSIONS) }
我必须运行基准测试,但这应该更快,因为如果编写不正确,正则表达式会使代码速度极慢。
你可以尝试:
TARGET_EXTENSION_RE = /\.(?:#{ Regexp.union(TARGET_EXTENSIONS).source})$/
# => /\.(?:mkv|avi|srt)$/
puts output.split(/\r?\n/).grep(TARGET_EXTENSION_RE)
因为锚定模式比未锚定模式快得多。
如果7z档案将生成大量列表(在MB范围内),则最好迭代输入以避免可伸缩性问题。在上面的例子中,output.lines
类似于扼杀输出。有关详细信息,请参阅“Why is "slurping" a file not a good practice?”。