Rubyで2つの文字列または配列のdiffを実行するにはどうすればよいですか?
diff.rbはあなたが欲しいものです。 http://users.cybercity.dk/~dsl8950/Ruby/diff.html インターネットアーカイブ経由:
http://web.archive.org/web/20140421214841/http://users.cybercity.dk:80/~dsl8950/Ruby/diff.html
配列の場合、マイナス演算子を使用します。例えば:
>> foo = [1, 2, 3]
=> [1, 2, 3]
>> goo = [2, 3, 4]
=> [2, 3, 4]
>> foo - goo
=> [1]
ここで最後の行は、gooにあるfooからすべてを削除し、要素1のみを残しています。配列、マイナス演算子を使用し、結果を元に戻します。
Rubyでこれに適したライブラリが不足していることに不満を感じていたので、 http://github.com/samg/diffy と書きました。カバーの下でdiff
を使用し、便利であり、きれいな出力オプションを提供することに焦点を当てています。
文字列の場合、まず、Ruby @ sam-saffronが以下で言及した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
@ 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
プラグイン。
もあります diff-lcs
これは宝石として入手可能です。 2004年以降は更新されていませんが、 問題なく使用しています。
編集:2011年に新しいバージョンがリリースされました。活発な開発に戻ったようです。
t=s2.chars; s1.chars.map{|c| c == t.shift ? c : '^'}.join
この単純な行は^
一致しない位置。多くの場合、これで十分であり、コピー/貼り付けが可能です。
Windowsの人々のためだけに、diffyは素晴らしいように見えますが、* nixでしか動作しないと信じています(間違っている場合は修正してください)。確かに私のマシンでは動作しませんでした。
Differは私にごtreat走をしました(Windows 7 x64、Ruby 1.8.7)。
私も同じ疑問を抱いており、私が見つけた解決策は100%Rubyではありませんが、私にとっては最適です。 diff.rbの問題は、人間向けに差分を表示するためのきれいなフォーマッタがないことです。だから私はこのコードでOSの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
文字解像度で文字を取得するには、新しい関数を 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
おそらく、モンキーパッチを介したArray.diffが役立ちます...
http://grosser.it/2011/07/07/Ruby-array-diffother-difference-between-2-arrays/