我的脚本读入大文本文件并使用正则表达式抓取第一页。我需要删除每个第一页的前两行或更改正则表达式以匹配== Page 1 ==字符串后的1行。我在这里包含了整个脚本,因为我在过去的问题中被问过,因为我是ruby的新手,并不总是知道如何整合片段作为答案:
#!/usr/bin/env ruby -wKU
require 'fileutils'
source = File.open('list.txt')
source.readlines.each do |line|
line.strip!
if File.exists? line
file = File.open(line)
end
text = (File.read(line))
match = text.match(/==Page 1(.*)==Page 2==/m)
puts match
end
答案 0 :(得分:3)
现在,当你更新了你的问题时,我不得不删除这么好的答案的一大部分: - )
我想您问题的主要内容是您想要使用match[1]
而不是match
。 Regexp.match
方法(MatchData
)返回的对象可以被视为一个数组,它将整个匹配的字符串保存为第一个元素,并将每个子查询保存在以下元素中。因此,在您的情况下,变量match
(和match[0]
)是整个匹配的字符串(与'== Page .. =='标记一起)< / em>,但您只想隐藏在match[1]
中的第一个子表达式。
现在我在您的代码中感觉到其他一些小问题。请不要被冒犯,以防你已经知道我说的话,但也许其他人会从警告中获益。
代码的第一个部分(if File.exists? line
)正在检查文件是否存在,但您的代码只是打开了文件(没有关闭它!)并且仍在尝试打开稍后提交几行。
您可以改用此行:
next unless File.exists? line
第二个的事情是程序应该准备好在文件没有页面标记时处理这种情况,因此它与模式不匹配。 (变量match
将为nil
)
第三建议可能会使用更复杂的模式。当前的一个(/==Page 1==(.*)==Page 2==/m
)将返回页面内容,并将End-Of-Line标记作为第一个字符。如果您使用此模式:
/==Page 1==\s*\n(.*)==Page 2==/m
然后子表达式将不包含与'== Page 1 ==`文本放在同一行中的空格。如果你使用这种模式:
/==Page 1==\s*\n(.*\n)==Page 2==/m
然后您将确保'== Page 2 =='标记从该行的开头开始。
第四个问题是,程序员(有时包括我,当然)往往忘记在打开文件后关闭文件。在您的情况下,您已打开'source'文件,但在代码中,循环后没有source.close
语句。处理文件最安全的方法是将块传递给File.open
方法,因此您可以使用程序第一行的以下形式:
File.open('list.txt') do |source|
source.readlines.each do |line|
...但在这种情况下,写下来会更清晰:
File.readlines('list.txt').each do |line|
总而言之,代码可能看起来像(我将变量line
更改为fname
以获得更好的代码可读性):
#!/usr/bin/env ruby -wKU
require 'fileutils'
File.readlines('list.txt').each do |fname|
fname.strip!
next unless File.exists? fname
text = File.read(fname)
if match = text.match(/==Page 1==\s*\n(.*\n)==Page 2==/m)
# The whole 'page' (String):
puts match[1].inspect
# The 'page' without the first two lines:
# (in case you really wanted to delete lines):
puts match[1].split("\n")[2..-1].inspect
else
# What to do if the file does not match the pattern?
raise "The file #{fname} does NOT include the page separators."
end
end