Search code examples
regexdiffgit-diff

Grepdiff not matching beginning or end of lines properly


I'm confused about some behavior in grepdiff. I'm trying to write a script that parses over individual hunks of a diff and looks for a pattern. In particular, I'm looking for diffs that add and remove a line with only a minor change in a numeric value, like this:

@@ -2160 +2160 @@
-        "posZ": 13.912,
+        "posZ": 13.911,

My goal is for the script to revert these changes. To do that, I need to detect them first. However, I can't get grepdiff to identify lines properly.

This regex does match:

git diff -U0 HEAD^ | grepdiff -E '^[^0-9-]*[0-9-]+.[0-9]+,' --output-matching=hunk 

This does not:

git diff -U0 HEAD^ | grepdiff -E '^[^0-9-]*[0-9-]+.[0-9]+,$' --output-matching=hunk 

Similarly, neither does this:

git diff -U0 HEAD^ | grepdiff -E '^\+[^0-9-]*[0-9-]+.[0-9]+,' --output-matching=hunk

Without matching the beginning or ending of lines properly, I don't see how I can identify these hunks.


Solution

  • Use

    grepdiff -E '^[^0-9-]*[0-9-]+[.][0-9]+,[[:space:]]*$'
    

    Explanation

    --------------------------------------------------------------------------------
      ^                        the beginning of the string
    --------------------------------------------------------------------------------
      [^0-9-]*                 any character except: '0' to '9', '-' (0
                               or more times (matching the most amount
                               possible))
    --------------------------------------------------------------------------------
      [0-9-]+                  any character of: '0' to '9', '-' (1 or
                               more times (matching the most amount
                               possible))
    --------------------------------------------------------------------------------
      [.]                      any character of: '.'
    --------------------------------------------------------------------------------
      [0-9]+                   any character of: '0' to '9' (1 or more
                               times (matching the most amount possible))
    --------------------------------------------------------------------------------
      ,                        ','
    --------------------------------------------------------------------------------
      [[:space:]]*             any character of: whitespace characters
                               (like \s) (0 or more times (matching the
                               most amount possible))
    --------------------------------------------------------------------------------
      $                        before an optional \n, and the end of the
                               string