#!/usr/bin/env perl # This program is part of Aspersa (http://code.google.com/p/aspersa/) =pod =head1 NAME rel - Make each number in a line of text relative to the previous matching line. =head1 SYNOPSIS Given a file with some lines of text that follow a repeated pattern, including numbers, rel /path/to/file.txt For example, if the text is this: Mutex spin waits 0, rounds 99584819933, OS waits 437663963 RW-shared spins 834337527, OS waits 20258150; RW-excl spins 1769749834 Mutex spin waits 0, rounds 99591465498, OS waits 437698122 RW-shared spins 834352175, OS waits 20259032; RW-excl spins 1769762980 The output will be Mutex spin waits 0, rounds 99584819933, OS waits 437663963 RW-shared spins 834337527, OS waits 20258150; RW-excl spins 1769749834 Mutex spin waits 0, rounds 6645565, OS waits 34159 RW-shared spins 14648, OS waits 882; RW-excl spins 13146 =head1 AUTHOR Baron Schwartz =cut use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); use constant MKDEBUG => $ENV{MKDEBUG}; my $file = shift @ARGV || '-'; my $fh; if ( $file eq '-' ) { $fh = *STDIN; } else { open $fh, "<", $file or die "Cannot open $file: $OS_ERROR"; } my @line_patterns; my %last_match; my %printf_for; while ( my $line = <$fh> ) { MKDEBUG && print "read: $line\n"; my $matched = 0; foreach my $pat ( @line_patterns ) { MKDEBUG && print "trying to match: $pat\n"; if ( my @vals = $line =~ m/$pat/ ) { MKDEBUG && print "matches\n"; $matched = 1; my @last_vals = @{ $last_match{$pat} }; my @offset_vals; for my $i ( 0..$#vals ) { $offset_vals[$i] = $vals[$i] - $last_vals[$i]; } $last_match{$pat} = \@vals; printf $printf_for{$pat}, @offset_vals; last; } } if ( !$matched ) { my $new_pat = $line; $new_pat =~ s/\d+/(\\d+)/g; my @vals = $line =~ m/$new_pat/; MKDEBUG && print "new pattern: $new_pat: @vals\n"; push @line_patterns, $new_pat; (my $printf_pat = $line ) =~ s/\d+/%d/g; $printf_for{$new_pat} = $printf_pat; $last_match{$new_pat} = \@vals; print $line; } } close $fh or warn "Cannot close $file: $OS_ERROR"; exit;