Regex 使用正则表达式筛选差异

Regex 使用正则表达式筛选差异,regex,git,diff,Regex,Git,Diff,似乎能够过滤一个差异,从而不显示琐碎的更改是非常方便的。我想写一个正则表达式,它将在该行上运行,然后将另一个字符串传递给它,该字符串使用捕获的参数生成规范形式。如果前后的行产生相同的输出,那么它们将从diff中删除 例如,我正在处理一个PHP代码库,其中大量的数组访问被写为my_array[my_key],而它们应该是my_array[“my_key”],以防止定义了my_key常量时出现问题。如果行中唯一的更改不是添加一些引号,那么生成一个diff将非常有用 我不能一次全部修改它们,因为我们没

似乎能够过滤一个差异,从而不显示琐碎的更改是非常方便的。我想写一个正则表达式,它将在该行上运行,然后将另一个字符串传递给它,该字符串使用捕获的参数生成规范形式。如果前后的行产生相同的输出,那么它们将从diff中删除

例如,我正在处理一个PHP代码库,其中大量的数组访问被写为
my_array[my_key]
,而它们应该是
my_array[“my_key”]
,以防止定义了
my_key
常量时出现问题。如果行中唯一的更改不是添加一些引号,那么生成一个diff将非常有用


我不能一次全部修改它们,因为我们没有足够的资源来测试整个代码库,所以每当我修改一个函数时,我都会解决这个问题。我怎样才能做到这一点?有没有其他类似的东西,我可以用来实现类似的结果。例如,一个更简单的方法可能是跳过规范形式,只看输入是否转换为输出。顺便说一句,我正在使用Git

$ git diff --help

-G<regex>
    Look for differences whose added or removed line matches the given <regex>.
然后我得到了如下输出:

diff --git a/test.php b/test.php
index 62a2de0..b76891f 100644
--- a/test.php
+++ b/test.php
@@ -1,3 +1,5 @@
<?php

{+$my_array[my_key]+} = "test";

?>
diff --git a/test1.php b/test1.php
index 62a2de0..6102fed 100644
--- a/test1.php
+++ b/test1.php
@@ -1,3 +1,5 @@
<?php

some_other_stuff();

?>

我使用了一种结合了
git diff
和对结果应用正则表达式匹配的方法。在一些测试代码(PERL)中,我知道当存储在测试结果文件中的
OutputFingerprint
没有更改时,测试是成功的

首先,我做一个

my $matches = `git diff -- mytestfile`
然后评估结果:

if($matches =~ /OutputFingerprint/){
  fail();
  return 1;
}else{
  ok();
  return 0;
}

在第一步中规范化输入文件,然后比较规范化文件。这使您能够对流程进行最大程度的控制。例如,您可能只想将regexp应用于代码的非HTML部分,而不是字符串内部,也不是注释内部(或者完全忽略注释)。 在规范化代码上计算一个diff是做这些事情的正确方法;在单行上使用regexp更容易出错,最多也是一种黑客行为


一些差异实用程序,例如
meld
允许隐藏“不重要”的差异,并附带一组默认模式,例如仅隐藏空白更改。我想,这正是你想要的。

< P>如果目标是最小化琐碎的差异,你可以考虑我们的工具。

这些工具比较的是语言语法,而不是布局,因此许多琐碎的更改(布局、修改的注释,甚至更改的数字基数)被忽略而不报告。 每个工具都有一个完整的语言解析器;有一个适用于多种语言的版本,包括PHP


它不会将示例$FOO[abc]处理为与$FOO[“abc”]在语义上相同,因为它们不是。如果abc实际上定义为常量,那么$FOO[“abc”]在语义上是不等价的。

Git的命令似乎没有任何选项来支持您想要做的事情。但是,您可以使用和自定义脚本(或使用首选脚本或编程语言创建的任何可执行文件)来操作修补程序

我假设你在Linux上;如果没有,您可以调整此概念以适应您的环境。假设您有一个Git回购,其中
HEAD
有一个文件
file05
,其中包含:

line 26662: $my_array[my_key]
line 19768: $my_array[my_key]
line 19769: $my_array[my_key]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key]
line 19776: $my_array[my_key]
以及包含以下内容的文件
file06

line 26662: $my_array[my_key]
line 19768: $my_array[my_key]
line 19769: $my_array[my_key]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key]
line 19776: $my_array[my_key]
file05
更改为:

line 26662: $my_array["my_key"]
line 19768: $my_array[my_key]
line 19769: $my_array["my_key"]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key2]
line 19776: $my_array[my_key]
然后将
file06
更改为:

line 26662: $my_array["my_key"]
line 19768: $my_array[my_key]
line 19769: $my_array["my_key"]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key2]
line 19776: $my_array[my_key]
使用下面的shell脚本,我们将其命名为
mydiff.sh
,并将其放置在
路径中的某个位置:

#!/bin/bash
echo "$@"
git diff-files --patch --word-diff=porcelain "${5}" | awk '
/^-./ {rec = FNR; prev = substr($0, 2);}
FNR == rec + 1 && /^+./ {
    ln = substr($0, 2);
    gsub("\\[\"", "[", ln);
    gsub("\"\\]", "]", ln);
    if (prev == ln) {
        print " " ln;
    } else {
        print "-" prev;
        print "+" ln;
    }
}
FNR != rec && FNR != rec + 1 {print;}
'
执行命令:

GIT_EXTERNAL_DIFF=mydiff.sh git --no-pager diff
将输出:

file05 /tmp/r2aBca_file05 d86525edcf5ec0157366ea6c41bc6e4965b3be1e 100644 file05 0000000000000000000000000000000000000000 100644
index d86525e..c2180dc 100644
--- a/file05
+++ b/file05
@@ -1 +1 @@
 line 26662: 
 $my_array[my_key]
~
file06 /tmp/2lgz7J_file06 d84a44f9a9aac6fb82e6ffb94db0eec5c575787d 100644 file06 0000000000000000000000000000000000000000 100644
index d84a44f..bc27446 100644
--- a/file06
+++ b/file06
@@ -1,8 +1,8 @@
 line 19768: $my_array[my_key]
~
 line 19769: 
 $my_array[my_key]
~
 line 19770: $my_array[my_key]
~
 line 19771: $my_array[my_key]
~
 line 19772: $my_array[my_key]
~
 line 19773: $my_array[my_key]
~
 line 19775: 
-$my_array[my_key]
+$my_array[my_key2]
~
 line 19776: $my_array[my_key]
~
此输出不显示
file05
file06
中添加的引号的更改。外部diff脚本基本上使用Git命令创建补丁,并通过脚本过滤输出以对其进行操作。此示例脚本不会处理中提到的新旧文件的所有不同组合,也不会输出有效的修补程序,但应该足以让您开始使用

您可以使用或任何您熟悉的工具来实现一个适合您需要的外部差异工具。

来自我自己的git--help

--word diff regex=

使用
来确定单词是什么,而不是将非空白字符视为单词。也意味着——单词diff除非 它已经启用。
的每个非重叠匹配都被视为一个单词。这些匹配之间的任何内容都被视为空白和空白 为查找差异而忽略(!)。您可能需要将
|[^[:space:]
附加到正则表达式以确保 它匹配所有非空白字符。包含换行符的匹配项在换行符处被自动截断(!)。 regex还可以通过diff驱动程序或配置选项进行设置,请参见gittributes(1)或git config(1)。明确地给出 覆盖任何差异驱动程序或配置设置。差异驱动程序覆盖配置设置

可以用来过滤diff文件中的大块

$ git diff -U1 | grepdiff 'console' --output-matching=hunk

它只显示与给定字符串“console”匹配的大块头。

我提供了一个类似问题的答案

我制作了一个git函数,将regex作为唯一的输入。只需将它输入您的gitconfig(我使用了我的全局gitconfig)并与
git regexadd
一起使用即可

[别名]
regexadd=“!f(){git diff-U0\
|grepdiff-E$1——输出匹配=hunk\
|git apply--cached--unidiff zero;};f“

这实际上没有为我显示任何选项。它们是否与正常的差异相同?@Casebash:请看我关于这个主题的问题:+1,因为它很有趣,但它不是我想要的,我发现了
--word diff regex
param,所以可能会有帮助。谢谢,这很有趣。它显示对一个单词的所有更改,这些更改要么最初与模式匹配,要么是c