【问题标题】: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 命令行工具?万一有所不同,代码是 PHP 和 Javascript 的混合体,所以我主要感兴趣的是忽略 ///* */#

【问题讨论】:

    标签: command-line-interface comments diff


    【解决方案1】:

    要使用视觉差异,您可以尝试MeldDiffMerge

    差异合并

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

    GNU diffutils

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

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

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

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

    我们可以阅读diffutils手册:

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

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

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


    另见:

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

    【讨论】:

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

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

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

    1. 如果原始代码库的最新版本是A 并且 最新的复制代码库是B,让我们用 为 A'B' 删除了 cmets(例如,在处理时将它们保存到临时文件中)。
    2. 找到一些常见的原始版本并将 cmets 从中剥离到 O' 中(或者只需为此重新使用 B')。
    3. 执行O'A'B' 的三向合并并保存到C'KDiff3 是一个很好的工具。
    4. 现在您有了想要合并的代码更改,但是 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
          

          【讨论】:

          猜你喜欢
          • 2011-03-26
          • 1970-01-01
          • 2011-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多