Merge of subsequent lines based on conditions in linux

Viewed 75

I have the below Raw log output of my software Installs and Upgrade times in a file. I need to record the progression of Software upgrades in Excel report and need the data in the expected output format. The beginning point is the Installation of the software and after that just upgrades are recorded in log.

  • Raw log output:
BIOS1,01/16/21 16:27:34,INSTALL,version-19.001-355
BIOS1,01/17/21 11:04:48,UPGRADE,version-19.001-361
BIOS1,02/14/21 07:22:37,UPGRADE,version-19.001-366
BIOS1,02/15/21 14:23:09,UPGRADE,version-19.001-372

So basically i need info of software upgrade progression that happened from
version-19.001-355 -> version-19.001-361 -> version-19.001-366 -> version-19.001-372

The expected output needed for my report after merging of lines with conditions is below in csv format. There is info of From_Version upgrade to the To_Version with upgrade dates

Name,     From_Version,    Upgraded_Date_Time,  State,     To_Version

BIOS1,  version-19.001-355, 01/17/21 11:04:48, UPGRADE,   version-19.001-361
BIOS1,  version-19.001-361, 02/14/21 07:22:37, UPGRADE,   version-19.001-366
BIOS1,  version-19.001-366, 02/15/21 14:23:09, UPGRADE,   version-19.001-372

I tried to merge the lines using :

awk 'NR%2 {printf("%s", $0); next} {print $0} ' data.txt

but the data is just merged and am not able to get in the desired way.

2 Answers

Keep the "version" across lines; the one from the currently processed line is to while the one from the previous line is from

use warnings;
use strict;
use feature 'say';

die "Usage: $0 file\n" if not @ARGV;

say join ',', qw(Name From_Version Upgraded_Date_Time State To_Version);

my $install_line = <>;  # shave off the first line
chomp $install_line;

my $from_version = (split /,/, $install_line)[-1];

while (<>) { 
    chomp;

    my ($name, $ts, $state, $version) = split /,/;

    say join ',', $name, $from_version, $ts, $state, $version;

    $from_version = $version;
}

I leave no spaces around commas so it's a proper CSV file (which Excel will like).

The "null filehandle" <> reads lines from files given on the command line. So you use this as

program_name filename

(make the script program_name executable, or do perl program_name filename)

You may use this awk:

awk -F, -v OFS=',  ' '
NR == 1 {
   print "Name,   From_Version,        Upgraded_Date_Time,  State,   To_Version"}
NR > 1 {
   $2 = p OFS $2
   print
}
{
   p = $NF
}' file

Name,   From_Version,        Upgraded_Date_Time,  State,   To_Version
BIOS1,  version-19.001-355,  01/17/21 11:04:48,  UPGRADE,  version-19.001-361
BIOS1,  version-19.001-361,  02/14/21 07:22:37,  UPGRADE,  version-19.001-366
BIOS1,  version-19.001-366,  02/15/21 14:23:09,  UPGRADE,  version-19.001-372
Related