我有这2个文件:
file1
Ruby
C
Visual Basic
R
Objective-C
Basic
HTML
file2
5. ab cde fg Java hij kl
2. ab PHP dddf llf
4. cde fg z o Objective-C oode
8. a12b cde JavaScript kdk
6. ab99r cde Visual Basic llso dkd
1. lkd dsk Ruby kksdk
3. Python dsdls
7. kdjd C jdjd
9. CSS dkdsk
7. kkd Basic jjs
3. rooor R kdk
我想搜索文件1中的字符串,如果在文件2中找到它们,然后打印“文件1的字符串”,然后打印文件2中的行号以及其中存在每个字符串的文件2的行。 / p>
输出格式如下:
找到文件1的“字符串” |找到文件1的“字符串”的文件2中的行|在file2中找到file1的“字符串”的行文本
对于示例文件1和文件2,我正在寻找的输出是:
Ruby|6|1. lkd dsk Ruby kksdk
C|8|7. kdjd C jdjd
Visual Basic|5|6. ab99r cde Visual Basic llso dkd
R|11|3. rooor R kdk
Objective-C|3|4. cde fg z o Objective-C oode
Basic|10|7. kkd Basic jjs
HTML|Not found
我尝试了以下代码,但没有找到任何东西。我的真实文件1大约有32K行,真实文件2大约有48K行。
require 'set'
f2_set = File.readlines("file2.txt").map(&:chomp).to_set
File.foreach("file1.txt") { |line| puts line if f2_set.include?(line) }
感谢您的帮助
更新
下面,我展示了@CarySwoveland提出的file1
和file2
,以及这些输入的output
会如何。
UPDATE2
答案 0 :(得分:1)
指出的问题没有正确的解决方案,因为没有办法解释Ruby Basic
(匹配器列表中最后一个元素旁边)匹配行6.
时不考虑 。需要更复杂的规则集才能完成所需的操作。
但这将是一个很好的起点:
matchers = File.readlines("file1.txt")
lines = File.readlines("file2.txt")
matchers.inject([]) do |acc, match|
acc | lines.each.with_index(1).map do |line, idx|
[match, idx, line].join("|") if line =~ /\b(#{match}\b)/
end.compact
end
#⇒ ["Ruby|6|1. lkd dsk Ruby kksdk",
# "C|3|4. cde fg z o Objective-C oode",
# "C|8|7. kdjd C jdjd",
# "Visual Basic|5|6. ab99r cde Visual Basic llso dkd",
# "R|11|3. rooor R kdk",
# "Objective-C|3|4. cde fg z o Objective-C oode",
# "Basic|5|6. ab99r cde Visual Basic llso dkd",
# "Basic|10|7. kkd Basic jjs"]
答案 1 :(得分:1)
我假设文件1的每一行最多出现在文件2的每一行中,文件2的每一行在文件1中包含的语言不超过一种,这与问题中给出的示例一致。
首先构造文件。为了使生活更有趣,我修改了问题中给出的两个文件的内容。
file1 =<<-END
Ruby
C
Visual Basic
C++
R
Objective-C++
Basic
HTML
END
FName1 = 'file1'
File.write(FName1, file1)
#=> 51
file2 =<<-END
5. ab cde fg Java hij kl
2. ab PHP dddf llf
4. cde fg z o Objective-C++ oode
8. a12b cde JavaScript kdk
6. ab99r cde Visual Basic llso dkd
1. lkd dsk Ruby kksdk
3. Python dsdls
7. kdjd C jdjd
9. CSS dkdsk
10. blah C++ blah
7. kkd Basic jjs
3. rooor R kdk
END
FName2 = 'file2'
File.write(FName2, file2)
#=> 256
首先将FName1
的行读入数组。
languages = File.readlines(FName1, chomp:true)
#=> ["Ruby", "C", "Visual Basic", "C++",
# "R", "Objective-C++", "Basic", "HTML"]
现在,为方便起见,将languages
的元素的长度减小。
sorted_languages = languages.sort_by(&:length).reverse
#=> ["Objective-C++", "Visual Basic", "Basic",
# "Ruby", "HTML", "C++", "C", "R"]
我已经通过减小字长来对languages
的元素进行了排序,以便在尝试将FName2
的行与'Objective-C ++'进行匹配之前进行尝试C ++”和“ C ++”将在“ C”之前考虑。同样,在考虑“基本”之前,“ Visual Basic”将被视为匹配项。
接下来,创建一个哈希,其键是FName1
中出现在FName2
行中的行,其值是散列,用于标识给定行FName2
中的行号和行键。
language_to_file2 = File.foreach(FName2, chomp: true).
with_index(1).
with_object({}) do |(line,n),h|
language = sorted_languages.find { |language| line.include?(language) }
h[language] = { line: line, nbr: n } unless language.nil?
end
#=> {"Objective-C++"=>{:line=>"4. cde fg z o Objective-C++ oode", :nbr=>3},
# "Visual Basic" =>{:line=>"6. ab99r cde Visual Basic llso dkd", :nbr=>5},
# "Ruby" =>{:line=>"1. lkd dsk Ruby kksdk", :nbr=>6},
# "C" =>{:line=>"7. kdjd C jdjd", :nbr=>8},
# "C++" =>{:line=>"10. blah C++ blah", :nbr=>10},
# "Basic" =>{:line=>"7. kkd Basic jjs", :nbr=>11},
# "R" =>{:line=>"3. rooor R kdk", :nbr=>12}}
我们现在可以显示所需的结果。
languages.each do |language|
print "#{language}|"
if language_to_file2.key?(language)
h = language_to_file2[language]
puts "%d|%s" % [h[:nbr], h[:line]]
else
puts "Not found"
end
end
Ruby|6|1. lkd dsk Ruby kksdk
C|8|7. kdjd C jdjd
Visual Basic|5|6. ab99r cde Visual Basic llso dkd
C++|10|10. blah C++ blah
R|12|3. rooor R kdk
Objective-C++|3|4. cde fg z o Objective-C++ oode
Basic|11|7. kkd Basic jjs
HTML|Not found