我有一个文件,我搜索特定的行,如下所示:
<ClCompile Include="..\..\..\Source\fileA.c" />
<ClCompile Include="..\..\..\Tests\fileB.c" />
在我的脚本中,我可以找到这些行并仅提取double qoutes之间的路径字符串。当我找到它们时,我将它保存到一个数组(我稍后在我的代码中使用)。它看起来像这样:
source_path_array = []
File.open(file_name) do |f|
f.each_line {|line|
if line =~ /<ClCompile Include="..\\/
source_path = line.scan(/".*.c"/)
###### Add path to array ######
source_path_array << source_path
end
}
end
到目前为止,一切都好。稍后在我的脚本中,我将另一个文件中的数组输出到“Source Files”行:
f.puts "Source Files= #{source_path_array.flatten.join(" ")}"
结果是这样的:
Source Files= "..\..\..\Source\fileA.c" "..\..\..\Tests\fileB.c"
我希望以这种形式输出:
Source Files=..\..\..\Source\fileA.c
Source Files=..\..\..\Tests\fileB.c
正如您所看到的,每个路径都在一个单独的行中,字符串“Source Files”之前也没有双引号。任何的想法?也许我对阵列的概念也不是最好的。
答案 0 :(得分:1)
然后不要使用#join
。使用#each
或#map
。此外,您可以使用#gsub
删除引号:
source_path_array.flatten.each do |path|
f.puts "Source Files=#{path.gsub(/(^"|")$/, '')}"
end
或
f.puts source_path_array.flatten.map do |path|
"Source Files=#{path.gsub(/(^"|")$/, '')}"
end.join("\n")
第二个版本的I / O效率可能更高。
要使其工作(并且作为问题第二部分的答案),source_path_array
应包含字符串。这是获得这个的方法:
regex = /<ClCompile Include="(\.\.\\[^"]+)/
File.open(file_name) do |f|
f.each_line do |line|
regex.match(line) do |matches|
source_path_array << matches[1]
end
end
end
如果您不介意一次读取内存中的整个文件,则会略短:
regex = /<ClCompile Include="(\.\.\\[^"]+)/
File.read(file_name).split(/(\r?\n)+/).each do |line|
regex.match(line) do |matches|
source_path_array << matches[1]
end
end
最后,这是使用Nokogiri的一个例子:
require 'nokogiri'
source_path_array = File.open(file_name) do |f|
Nokogiri::XML(f)
end.css('ClCompile[Include^=..\\]').map{|el| el['Include']}
所有这些都会解析引号,因此您可以从第一部分中删除#gsub
。
现在一起:
require 'nokogiri'
f.puts File.open(file_name) do |source|
Nokogiri::XML(source)
end.css('ClCompile[Include^=..\\]').map do |el|
"Source Files=#{el['Include']}"
end.join("\n")
并且当一次(单个#map
)可行时,不要循环两次(#join
然后#reduce
):
require 'nokogiri'
f.puts File.open(file_name) do |source|
Nokogiri::XML(source)
end.css('ClCompile[Include^=..\\]').reduce('') do |memo, el|
memo += "Source Files=#{el['Include']}\n"
end.chomp
答案 1 :(得分:0)
感谢@FélixSaparelli:
以下对我有用:
source_path_array.flatten.each do |path|
f.puts "Source Files=#{path.delete('"')}"
end