这是一个逐行读取文件的 Ruby 解决方案。最后,我展示了如果可以将文件吞入字符串,解决方案会变得多么简单。
让我们首先创建一个要使用的输入文件。
str =<<~_
apple|pear
apple|quince
apple cider|juice
banana|plantain
cherry|cheerful, crimson
cherry|ruddy
cherry|cerise
_
file_name_in = 'file_in'
File.write(file_name_in, str)
#=> 112
逐行读取文件时的解决方案
我们可以使用以下方法生成所需的输出文件。
def doit(file_name_in, file_name_out)
fin = File.new(file_name_in, "r")
fout = File.new(file_name_out, "w")
str = ''
until fin.eof?
s = fin.gets.strip
k,v = s.split(/(?=\|)/)
if str.empty?
str = s
key = k
elsif k == key
str << v
else
fout.puts(str)
str = s
key = k
end
end
fout.puts(str)
fin.close
fout.close
end
让我们试试看。
file_name_out = 'file_out'
doit(file_name_in, file_name_out)
puts File.read(file_name_out)
打印以下内容。
apple|pear|quince
apple cider|juice
banana|plantain
cherry|cheerful, crimson|ruddy|cerise
注意
"apple|pear".split(/(?=\|)/)
#=> ["apple", "|pear"]
正则表达式包含与和之间的零宽度位置匹配的正前瞻 。(?=\|)
'e'
'|'
文件被吞入字符串时的解决方案
OP 不想将文件吞入一个字符串(因此我在上面的解决方案),但我想说明如果可以这样做,问题会变得多么简单。这是执行此操作的众多方法之一。
def gulp_it(file_name_in, file_name_out)
File.write(file_name_out,
File.read(file_name_in).gsub(/^(.+)\|.*[^ ]\K *\r?\n\1/, ''))
end
gulp_it(file_name_in, file_name_out)
#=> 98
puts File.read(file_name_out)
印刷
apple|pear|quince
apple cider|juice
banana|plantain
cherry|cheerful, crimson|ruddy
cherry|cerise
考虑一下正则表达式引擎将要做什么,这可能是可以接受的快,当然取决于文件大小。
正则表达式演示
虽然链接使用 PCRE 引擎,但使用 Ruby 的正则表达式引擎 (Onigmo) 的结果将是相同的。我们可以通过以自由间距模式编写正则表达式自记录。
/
^ # match the beginning of a line
(.+) # match one or more characters
\|.*[^ ] # match '|', then zero or more chars, then a non-space
\K # resets the starting point of the match and discards
# any previously-matched characters
[ ]* # match zero or more chars
\r?\n # march the line terminator(s)
\1 # match the content of capture group 1
/x # invoke free-spacing mode
(.+)
匹配, 'apple'
,'banana'
并且'cherry'
因为这些词在开头行。一个也可以写([^|]*)
。