如何正确解析统一差异中的范围信息?

How do I properly parse the range information in a unified diff?

基本上,我想做的就是看一个统一的diff的范围信息,然后确切地知道我应该关注哪些代码行。

例如,这个:

@@ -1827,7 +1827,7 @@

这告诉我总共只有 1 行发生了变化,因为差异显示了变化上下 3 行(所以 7 - 6 = 1),它还指向 1830 行(即 1827 + 3).

更迂腐地说,这个特定的范围信息实际上告诉我,在第 1830 行,删除了一行 (-),并在第 1830 行添加了一行 (+)。

或者为了更明显地考虑另一个差异的范围信息:

@@ -878,15 +878,13 @@

这告诉我的是,在第 881 行 (878 + 3) 删除了 9 行 (15 - 6),但在第 881 行仅添加了 7 行 (13 - 6)。

所以问题是,使用正则表达式或其他一些 Ruby 字符串方法,如何轻松提取上述信息?

即我如何轻松提取此信息:

我尝试对字符串进行切片并直接找到一个字符——例如myString[3] 这给了我 -,但这是它唯一可靠工作的字符,因为行号可以是 1、10、100、1000、10000 等。所以唯一的方法就是扫描字符串然后解析它。

编辑 1

添加一些代码来展示我的尝试。

假设我在名为 @diff_lines:

的变量中有差异的内容
@diff_lines.each do |diff_line|
  if diff_line.start_with?("@@")
    del_line_num_start = diff_line.split(/@@ /).second.split.first.split(/-/).second.split(/,/).first.to_i + 3
    num_deleted_lines = diff_line.split(/@@ /).second.split.first.split(/-/).second.split(/,/).second.to_i - 6
    add_line_num_start = diff_line.split(/@@ /).second.split.second.split(/\+/).second.split(/,/).first.to_i + 3
    num_added_lines = diff_line.split(/@@ /).second.split.second.split(/\+/).second.split(/,/).second.to_i - 6

如您所见,上面的方法有效....但看起来很可怕,而且显然不是很干。

理想情况下,我希望能够实现同样的事情,但更干净。

总体思路是编写一个包含捕获组 ((...)) 的正则表达式,以将该字符串分解为有用的内容。例如:

diff_line.match(/\A@@\s+\-(\d+),(\d+)\s+\+(\d+),(\d+)\s+@@/)

这会在成功匹配时产生一个 MatchData 对象。然后,您可以将其应用于某些变量,例如:

if (m = diff_line.match(...))
  a_start, a_len, b_start, b_len = m[1..4].map(&:to_i)
end

然后你可以用这些数字做任何你需要做的计算。

如果您在想象正则表达式的作用时遇到困难,请尝试使用像 Rubular 这样的工具来更好地说明内部结构。