it-swarm.cn

diff一个Ruby字符串或数组

如何在Ruby中进行两个字符串或数组的差异?

54
Josh Moore
20
Brian Mitchell

对于数组,请使用减号运算符。例如:

>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]

这里最后一行删除foo中的所有东西,也就是goo,只剩下元素1.我不知道如何为两个字符串执行此操作,但是直到有人知道有关它的帖子,你可以将每个字符串转换为数组,使用减号运算符,然后将结果转换回来。

32
Chris Bunch

我对Ruby中缺少一个好的库感到沮丧,所以我写了 http://github.com/samg/diffy 。它使用了diff,并专注于方便,并提供漂亮的输出选项。

22
samg

对于字符串,我会首先尝试@sam-saffron在下面提到的Ruby Gem。它更容易安装: http://github.com/pvande/differ/tree/master

gem install differ

irb
require 'differ'

one = "one two three"
two = "one two 3"

Differ.format = :color
puts Differ.diff_by_Word(one, two).to_s

Differ.format = :html
puts Differ.diff_by_Word(one, two).to_s
19
da01

@ da01上面提到的HTMLDiff为我工作。

script/plugin install git://github.com/myobie/htmldiff.git

# bottom of environment.rb
require 'htmldiff'

# in model
class Page < ActiveRecord::Base
  extend HTMLDiff
end

# in view
<h1>Revisions for <%= @page.name %></h1>
<ul>
<% @page.revisions.each do |revision| %>
  <li>
    <b>Revised <%= distance_of_time_in_words_to_now revision.created_at %> ago</b><BR>
      <%= Page.diff(
        revision.changes['description'][0],
        revision.changes['description'][1]
      ) %>
      <BR><BR>
  </li>
<% end %>

# in style.css
ins.diffmod, ins.diffins { background: #d4fdd5; text-decoration: none; }
del.diffmod, del.diffdel { color: #ff9999; }

看起来很不错。顺便说一句,我将它用于acts_as_audited插件。

5
Brian Armstrong

还有diff-lcs可用作宝石。 它自2004年以来没有更新过 我们一直在使用它没有任何问题。

编辑: 2011年发布了一个新版本。看起来它正在积极开发中。

http://rubygems.org/gems/diff-lcs

5
Grant Hutchins
t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join

这个简单的行在不匹配的位置给出^。这通常就够了,它可以复制/粘贴。

3
Steve

只是为了Windows用户的利益:diffy看起来很棒,但我相信它只适用于* nix(如果我错了,请纠正我)。当然它在我的机器上不起作用。

不同之处对我有用(Windows 7 x64,Ruby 1.8.7)。

2
russthegibbon

我刚刚发现了一个看起来非常灵活的新项目:

http://github.com/pvande/differ/tree/master

尝试一下,并尝试发布某种报告。

2
Sam Saffron

我有同样的疑问,我找到的解决方案不是100%Ruby,但对我来说是最好的。 diff.rb的问题在于它没有漂亮的格式化程序,以人性化的方式显示差异。所以我使用这段代码从操作系统中使用了diff:

 def diff str1, str2
   system "diff #{file_for str1} #{file_for str2}"
 end

 private
 def file_for text
   exp = Tempfile.new("bk", "/tmp").open
   exp.write(text)
   exp.close
   exp.path
 end
2
Daniel Cukier

为了通过角色分辨率获得角色,我在 damerau-levenshtein gem中添加了一个新函数

require "damerau-levenshtein"
differ = DamerauLevenshtein::Differ.new
differ.run "Something", "Smothing"
# returns ["S<ins>o</ins>m<subst>e</subst>thing", 
#  "S<del>o</del>m<subst>o</subst>thing"]

或者解析:

require "damerau-levenshtein"
require "nokogiri"

differ = DamerauLevenshtein::Differ.new
res = differ.run("Something", "Smothing!")
nodes = Nokogiri::XML("<root>#{res.first}</root>")

markup = nodes.root.children.map do |n|
  case n.name
  when "text"
    n.text
  when "del"
    "~~#{n.children.first.text}~~"
  when "ins"
    "*#{n.children.first.text}*"
  when "subst"
    "**#{n.children.first.text}**"
  end
end.join("")

puts markup
1
dimus
1
grosser