如何执行忽略所有评论的差异?

Posted

技术标签:

【中文标题】如何执行忽略所有评论的差异?【英文标题】:How can I perform a diff that ignores all comments? 【发布时间】:2011-11-22 04:11:49 【问题描述】:

我有一个从原始项目分叉的大型代码库,我正在尝试找出与原始项目的所有差异。许多文件编辑由注释掉的调试代码和其他杂项 cmets 组成。 Ubuntu 下名为 Meld 的 GUI diff/merge 工具可以忽略 cmets,但只能忽略单行 cmets。

是否有任何其他方便的方法可以仅查找非注释差异,无论是使用 GUI 工具还是 linux 命令行工具?万一有所不同,代码是 phpjavascript 的混合体,所以我主要感兴趣的是忽略 ///* */#

【问题讨论】:

【参考方案1】:

要使用视觉差异,您可以尝试Meld 或DiffMerge。

差异合并

其规则集和选项提供自定义行为。

GNU diffutils

从命令行的角度来看,您可以使用--ignore-matching-lines=RE 选项来代替diff,例如:

diff -d -I '^#' -I '^ #' file1 file2

请注意,正则表达式必须匹配两个文件中的相应行,并且它匹配大块中每个更改的行才能工作,否则它仍然会显示差异。

使用单引号保护模式免受外壳扩展和转义正则表达式保留的字符(例如括号)。

我们可以阅读diffutils手册:

但是,-I 仅在块中每个更改的行(每个插入和每个删除)都与正则表达式匹配时,才会忽略包含正则表达式的行的插入或删除。

换句话说,对于每个不可忽略的更改,diff 会在其附近打印完整的更改集,包括可忽略的更改。您可以使用多个-I 选项为要忽略的行指定多个正则表达式。 diff 尝试将每一行与每个正则表达式匹配,从给定的最后一个开始。

armel here 也很好地解释了这种行为。


另见:

How to diff files ignoring comments (lines starting with #)?

或者,检查其他差异应用程序,例如:

对于 macOS:Code compare and merge tools 对于 Windows:3-way merge tools for Windows

【讨论】:

我想知道如何设置 DiffMerge 以忽略 C/C++ 代码的注释行。尤其是在比较文件夹时。【参考方案2】:

您可以先通过stripcmt 过滤这两个文件,这将删除 C 和 C++ cmets。对于删除 # cmets,sed 's/#.*//' 将删除这些。

当然,当首先删除 cmets 时,您会失去一些上下文,但另一方面, cmets 的差异不会造成任何问题。我想我会这样做(针对单个文件进行描述,根据需要自动执行):

    如果原始代码库的最新版本是A 并且 最新的复制代码库是B,让我们用 为 A'B' 删除了 cmets(例如,在处理时将它们保存到临时文件中)。 找到一些常见的原始版本并将 cmets 从中剥离到 O' 中(或者只需为此重新使用 B')。 执行O'A'B' 的三向合并并保存到C'。 KDiff3 是一个很好的工具。 现在您有了想要合并的代码更改,但是 C' 没有 cmets,所以回到“正常”模式,以 A' 为基础和 A 和 @987654339 进行新的 3 路合并@。这会将 A'C' 之间的更改(这是您想要的代码更改)提取到基于版本 A 的 cmets 的普通代码库中。

强烈建议您在开始之前在纸上绘制版本树,以便清楚地了解您要处理的版本。但是不要受限于树显示的内容,如果您只是弄清楚要使用哪些版本,您可以merge any version and in any direction。

【讨论】:

【参考方案3】:
diff <file1> <file2> | grep -v '^[<>]\ #'

远非完美,但它会让你了解差异

【讨论】:

【参考方案4】:

请参阅我们的Smart Differencer 工具系列,它使用语言结构而不是作为指南的布局来比较计算机语言源文件。这尤其意味着它在比较代码时会忽略 cmets 和空格。

有一个SmartDifferencer for PHP。

【讨论】:

PS:马特,我们也在奥斯汀。 @TomasTintera:嗯,我们认为 SmartDiff 非常聪明。您能否更清楚地了解您尝试了哪种语言(PHP?Java?...)Smart Diff,以及没有产生您所期望的情况/实际情况,正是您所期望的? (您可以将示例发送到“support@semanticdesigns.com”,我们会查看)。 @TomasTintera:我注意到 OP 正在寻找一种可以忽略评论(更改)的工具。 SmartDiff 执行 OP 要求的操作。 当然。谢谢你的提醒。删除了我的评论,因为它属于另一个问题和答案。【参考方案5】:

gnu diff 支持忽略匹配正则表达式的行:

diff --ignore-matching-lines='^#' file1 file2

对于文件夹:

diff -[bB]qr --ignore-matching-lines='^#' folder1/ folder2/

这将忽略所有以 # 开头的行。

【讨论】:

This would ignore all lines which start with a # at the line beginning。这不是真的。 --ignore-matching-lines 的行为不同。【参考方案6】:

我试过了:diff file1 file2diff -d -I ^#.\* file1 file2 两种情况下的结果都是一样的 - 包括 cmets;

但是,diff -u file1 file2 | grep -v '^ \|^.#\|^.$' 给出了 我需要的是:只有真正的差异,没有 cmets,没有空行。 ;)

【讨论】:

【参考方案7】:

试试:

diff -I REGEXP -I REGEXP2 file1 file 2

参见:Regular expression ***

以下是正则表达式的示例,它们会导致差异忽略预处理器指令和标准注释块类型。

例如:

\#*\n
/***/
//*\n

【讨论】:

不,--ignore-matching-lines 并没有完全消灭 cmets。

以上是关于如何执行忽略所有评论的差异?的主要内容,如果未能解决你的问题,请参考以下文章

如何评论为啥可以忽略捕获

如何在 GitLab 中查看合并审阅评论和文件更改?

如何检索分支上元素的结帐评论?

正则表达式 - 获取引号中的字符串忽略转义的引号和评论

获取 mysql 行,除非它是重复的,在这种情况下忽略它

如何在 Rails 中创建通知系统?