Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

treat diff file in perl

by Anonymous Monk
on May 25, 2023 at 07:32 UTC ( [id://11152408]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Esteemed Monks,

how treat a json diff in perl?
my @diff = <<EOF @@ -3,7 +3,7 @@; id : 6109; name: abc; value: 0; - status: ?; + status: C; time: 2023-01-01 12:00; @@ -3,8 +3,8 @@; id : 6109; name: abc; - value: 0; - status: ?; + value: 2 + status: CS; time: 2023-01-01 12:03; @@ -3,7 +3,7 @@; id : 6109; name: abc; value: 0; - status: ?; + status: C; time: 2023-01-01 12:05; EOF
how print every change sorted by id like:
6109 changed on 2023-01-01 12:00, before status is ? +after is C. 6109 changed on 2023-01-01 12:03, before value is 0 a +fter is 2, before status is ? after is CS. ......
I've searched on CPAN, but all module about diff are generate or apply diff but not treat it. is there a module or convenient way to solve this? Thanks in advance.

Replies are listed 'Best First'.
Re: treat diff file in perl
by Corion (Patriarch) on May 25, 2023 at 07:35 UTC

    What you have is not specific to JSON.

    Most likely you can simply walk through the diff file and output the changes. If the diff file does not have enough context, you have to read the original and then apply the diff to output the changes.

    What code have you already written to process the diff file?

Re: treat diff file in perl
by tybalt89 (Monsignor) on May 25, 2023 at 16:40 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11152408 use warnings; $SIG{__WARN__} = sub { die $@ }; # NOTE missing ; was added my $diff = <<EOF; # NOTE $ not @ @@ -3,7 +3,7 @@; id : 6109; name: abc; value: 0; - status: ?; + status: C; time: 2023-01-01 12:00; @@ -3,8 +3,8 @@; id : 6109; name: abc; - value: 0; - status: ?; + value: 2; + status: CS; time: 2023-01-01 12:03; @@ -3,7 +3,7 @@; id : 6109; name: abc; value: 0; - status: ?; + status: C; time: 2023-01-01 12:05; EOF my @ids; for ( split /(?=^\s*@@)/m, $diff ) { # print "----------------------------------------\n$_\n\n"; my ($id) = /^\s*id : (\d+)/m; my ($time) = /^\s*time: (.+);/m; my @fields; push @fields, "before $1 is $2 after is $3" while /^\s*- (\w+): (.+);\n(?=(?:.*\n)*\s*\+ \1: (.*);\n)/gm; local $" = ', '; push @ids, "$id changed on $time, @fields.\n"; } print sort { $a =~ s/ .*//sr <=> $b =~ s/ .*//sr } @ids;

    Outputs:

    6109 changed on 2023-01-01 12:00, before status is ? after is C. 6109 changed on 2023-01-01 12:03, before value is 0 after is 2, before + status is ? after is CS. 6109 changed on 2023-01-01 12:05, before status is ? after is C.
Re: treat diff file in perl
by hv (Prior) on May 25, 2023 at 12:19 UTC

    In the general case, there is not enough information in a diff file (in isolation) to be able to give such context - because in the general case there is no guarantee that unchanged entries such as the id will appear in the context lines. Because of that there is unlikely to be a general-purpose module available for this.

    In your specific case, maybe it is possible - if the JSON is guaranteed to be short enough that the id and timestamp will always appear in the context lines. In that case, a hand-rolled parser for the diff chunks should be easy to construct and use; you may be able to get a leg-up by finding something that already parses diff files (such as the inline "Patch" class in patch, part of PerlPowerTools), but it may well be overkill for your needs.

Re: treat diff file in perl -- oneliner
by Discipulus (Canon) on May 26, 2023 at 08:21 UTC
    Hello,

    the problem sounded intriguing and, for my own amusement I got this, where the output is not exactly what asked for but still human readable:

    perl -n0E "map{for(join'|',split/\n/){$r{$2}=$1if/(.*)time: (.*);/}map +{s/-/BEFORE/g;s/\+/AFTER/g;s/.*id : (\d+);.*name: \w+;/ IN \1 /;s/[;| + ]+/ /g}values%r}split/^.*@;/m;say$_.$r{$_}for sort keys%r" diff-exam +ple.txt 2023-01-01 12:00 IN 6109 value: 0 BEFORE status: ? AFTER status: C 2023-01-01 12:03 IN 6109 BEFORE value: 0 BEFORE status: ? AFTER value: + 2 AFTER status: CS 2023-01-01 12:05 IN 6109 value: 0 BEFORE status: ? AFTER status: C

    The oneliner became ugly and longish for the text formatting, while a shorter one still has an acceptable output:

    perl -n0E "map{for(join'',split/\n/){$r{$2}=$1if/(.*)time:(.*)/}}split +/.*@;/m;say$_.$/.$r{$_}for sort keys%r"

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: treat diff file in perl
by bliako (Monsignor) on May 25, 2023 at 20:51 UTC

    Just in case you have the JSON data available and not just their diff:

    Read in the JSON data and convert them into a Perl data structure. Then use Struct::Diff to compare them and show their differences (assuming you overcome deciphering diff's output).

    bw, bliako

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11152408]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (12)
As of 2024-04-23 14:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found