How to convert the row to column in Perl?


Login or Register for Dates, Times and to Reply

 
Thread Tools Search this Thread
# 1  
How to convert the row to column in Perl?

Dear Perl users,

Could you help me how to convert from row to column if I've a case below:

Code:
Linux           2014_01_24           CPU            10
Linux          2014_01_24            MEM        20
UNIX          2014_01_24           CPU            30
UNIX         2014_01_24            MEM        40

and the desired output will be :

Code:
NAME      TIME                Linux           UNIX
CPU       2014_01_24         10                 30         
MEM     2014_01_24          20                40

Thank you very much

Last edited by Scrutinizer; 02-25-2014 at 02:59 AM.. Reason: code tags instead of icode tags
# 2  
You can try this with Shell like below :_


Code:
#!/bin/sh
awk 'BEGIN{print "NAME\tTIME\tLinux\tUNIX"}' > output.txt
grep -i mem test | paste -s - | awk '{print $3"\t"$2"\t"$4"\t"$8}' >>output.txt
grep -i CPU test | paste -s - | awk '{print $3"\t"$2"\t"$4"\t"$8}' >>output.txt


Here is your desired output:-

Code:
cat output.txt


 
NAME    TIME    Linux   UNIX
MEM     2014_01_24      20      40
CPU     2014_01_24      10      30


Last edited by Scrutinizer; 02-25-2014 at 02:59 AM.. Reason: code tags
# 3  
python

Code:
import itertools
import operator
a='''Linux 2014_01_24 CPU 10
Linux 2014_01_24 MEM 20
UNIX 2014_01_24 CPU 30
UNIX 2014_01_24 MEM 40'''.split("\n")
a=map(lambda x:x.split(" "),a)
for name,item in itertools.groupby(sorted(a,key=operator.itemgetter(2,1)),operator.itemgetter(2,1)):
    print(name[0],name[1],end=" ")
    for i in item:
        print(i[-1],end=" ")
    print("")

# 4  
Code:
perl -lane 'BEGIN {print "NAME TIME Linux UNIX"};
if ($F[0] eq "Linux") {
    ${ $x{"$F[2] $F[1]"} }[0] = $F[3];
}
elsif ($F[0] eq "UNIX") {
    ${ $x{"$F[2] $F[1]"} }[1] = $F[3];
}
END { print "$_ ${ $x{$_} }[0] ${ $x{$_} }[1]" for (keys %x) }' file

# 5  
Hi Belajesuri,
Thanks alot for your Perl code and to the others also I would like to say thanks so much but I need a Perl script.

I try to reformat your code from one-liners to the common way of Perl language and it works.

My next question is how I can set the header "Linux" and "UNIX" as variables instead of static values?. so when the other line comes, the header will be added also as well as the value of CPU anf MEM (e.g. )?.
Code:
Linux           2014_01_24            CPU            10
Linux           2014_01_24            MEM            20
UNIX            2014_01_24            CPU            30
UNIX            2014_01_24            MEM            40
WINDOWS         2014_01_24            CPU            70
WINDOWS         2014_01_24            MEM            80

so the result will be = NAME TIME Linux UNIX WINDOWS.. so on

Code:
#!/usr/bin/perl
use strict;

my %table;

print "NAME TIME  Linux UNIX\n";

foreach (<FH>)
{  chomp;
   my @temp = split " ", $_;
   
   if ($temp[0] eq "Linux")
   {
       $table{"$temp[2] $temp[1]"}[0] = $temp[3];   
   }
   elsif($temp[0] eq "UNIX")
   {
       $table{"$temp[2] $temp[1]"}[1] = $temp[3];   
   }
    
}

print "$_ ${$table{$_}}[0] ${ $table{$_} }[1]" for (keys %table);

---------- Post updated at 10:19 PM ---------- Previous update was at 04:17 PM ----------

Hi Balajesuri,

I've made the script based on your original code and the desired output already oke. But I think my script is still ugly. may be you have a good solution for this?.

Code:
#!/usr/bin/perl
use strict;
use Data::Dumper;

my %table;

my $file = "convert_column.log";

open (FH, "<", $file) or die $!;

my @node_name;

foreach my $line (<FH>)
{
  chomp;
  my @temp = split " ", $line;
  push @node_name, $temp[0];
}

my %seen;
my @node_name_without_duplicate;

for (@node_name)
{
  $seen{$_}++;
  next if $seen{$_}++>1;
  push @node_name_without_duplicate, $_;
}


close (FH);

my $length_node = scalar @node_name_without_duplicate;
print "NAME TIME  @node_name_without_duplicate\n";
open (FH, "<", $file) or die $!;

my %table;  

foreach (<FH>)
{
    for my $i (0 .. $length_node-1)
    {    
      my @temp = split " ", $_;
      if ($temp[0] eq $node_name_without_duplicate[$i])
      { 
        $table{"$temp[2] $temp[1]"}[$i] = $temp[3];
      }
    }    
}
close (FH);
   
for (keys %table)
{
    
        print "$_ ";
    for my $i (0 .. $length_node-1)
    {
      print " $table{$_}->[$i]";
        }

    print "\n";
}

# 6  
You are reading the file twice - this should be avoided, unless absolutely necessary.

Code:
#! /usr/bin/perl
use warnings;
use strict;

my ($line, $k1, $k2);
my (@fld, @temp);
my (%os, %final);

open I, "< file";
while ( $line = <I> ) {
    chomp ( $line );
    @fld = split /\s+/, $line;
    $os{$fld[0]} = 1;
    ${ $final{"$fld[2] $fld[1]"} }{$fld[0]} = $fld[3];
}
close I;

my @OS_list = sort ( keys %os );
print "NAME TIME @OS_list\n";

for $k1 ( keys %final ) {
    print "$k1 ";
    for $k2 ( @OS_list ) {
        if ( defined ${ $final{$k1} }{$k2} ) {
            print "${ $final{$k1} }{$k2} ";
        }
        else {
            print "--- ";
        }
    }
    print "\n";
}

Code:
[user@host ~]$ cat file
Linux           2014_01_24            CPU            10
Linux           2014_01_24            MEM            20
UNIX            2014_01_24            CPU            30
UNIX            2014_01_24            MEM            40
WINDOWS         2014_01_24            CPU            70
WINDOWS         2014_01_24            MEM            80
HPUX            2014_01_22            CPU            90
HPUX            2014_01_22            MEM            100
[user@host ~]$ ./test.pl
NAME TIME HPUX Linux UNIX WINDOWS
MEM 2014_01_22 100 --- --- ---
MEM 2014_01_24 --- 20 40 80
CPU 2014_01_24 --- 10 30 70
CPU 2014_01_22 90 --- --- ---
[user@host ~]$

# 7  
I know you want a perl script but here a solution in awk just for the fun of it

Code:
awk '
  {
    if(!($1 in os)) { os[$1]=++i; ios[i]=$1 }
    com[$3]; date[$2]
    data[$3, os[$1], $2]=$4
  }
  END{
    printf("%-11s%-11s", "NAME", "TIME")
    for(a=1; a<=i; a++) printf("%-11s", ios[a])
    printf "\n"
    for(b in com){
      for(c in date){
        p=0; str=""
        for(j=1; j<=i; j++){
          if(data[b, j, c]) p=1
          str=str sprintf("%-11s", data[b, j, c]?data[b, j, c]:"---")
        }
        if(!p) continue
        printf("%-11s%-11s%s\n", b, c, str)
      }
    }
  } ' infile

Code:
root@maximus-netpune-21:/tmp# ./run
NAME       TIME       Linux      UNIX       WINDOWS    HPUX
CPU        2014_01_22 ---        ---        ---        90
CPU        2014_01_24 10         30         70         ---
MEM        2014_01_22 ---        ---        ---        100
MEM        2014_01_24 20         40         80         ---

--ahamed

Last edited by ahamed101; 02-25-2014 at 04:39 PM..
Login or Register for Dates, Times and to Reply

Previous Thread | Next Thread
Thread Tools Search this Thread
Search this Thread:
Advanced Search

Test Your Knowledge in Computers #367
Difficulty: Medium
The Single UNIX Specification specifies vi, so every conforming UNIX system must have it.
True or False?

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Convert Data from Column to Row

Hi FileA.txt E_TIM 16, ETE 15, EOND 26, EEC 81, E_1 un, E_2 un, E_3 un, E_4 284, E_TIM 17, ETE 15, EOND 29, EEC 82, E_1 un, E_2 un, E_3 un, E_4 249, (6 Replies)
Discussion started by: asavaliya
6 Replies

2. Shell Programming and Scripting

[Solved] Convert Row To column

Hi Folks, I am using db2 command -> db2 list tablespace show detail Tablespace ID = 10 Name = TSCDDHLMSUM Type = Database managed space Contents = All permanent data.... (5 Replies)
Discussion started by: ckwan
5 Replies

3. Shell Programming and Scripting

Script: Convert row in to column

Hi, i need to convert SG_ERP1 SG_ERP2 SG_ERP3 in to: SG_ERP1 SG_ERP2 SG_ERP3 It's possibile? (16 Replies)
Discussion started by: elilmal
16 Replies

4. Shell Programming and Scripting

convert row to column with respect of first column.

Input file A.txt :- C2062 -117.6 -118.5 -117.5 C5145 0 0 0 C5696 0 0 0 Output file B.txt C2062 X -117.6 C2062 Y -118.5 C2062 Z -117.5... (4 Replies)
Discussion started by: asavaliya
4 Replies

5. UNIX for Dummies Questions & Answers

awk: convert column to row in a specific way

Hi all! I have this kind of output: a1|b1|c1|d1|e1 a2|b2|c2 a3|b3|c3|d3 I would like to transpose columns d and e (when they exist) in column c, and under the row where they come from. Then copying the beginning of the row. In order to obtain: a1|b1|c1 a1|b1|d1 a1|b1|e1 a2|b2|c2... (1 Reply)
Discussion started by: lucasvs
1 Replies

6. Shell Programming and Scripting

Convert row to column

Hi, I have a file like this 50 1 2 1374438 50 1 2 1682957 50 5 2 1453574 50 10 2 1985890 100 1 2 737307 100 5 2 1660204 100 10 2 2148483 and I want to convert this by... (1 Reply)
Discussion started by: gvj
1 Replies

7. Shell Programming and Scripting

convert a column to row output?

Getting tired of cut-and-paste...so I thought I would post a question. how do I change this column output to a single row? from this: # vgdisplay -v /dev/vgeva05 | grep dsk | awk '{print $3}' /dev/dsk/c6t0d5 /dev/dsk/c11t0d5 /dev/dsk/c15t0d5 /dev/dsk/c18t0d5 /dev/dsk/c7t0d5... (8 Replies)
Discussion started by: mr_manny
8 Replies

8. Shell Programming and Scripting

Convert column values into row

hi, I have a requirement where in I read the values from a file using awk. The resulting data should be converted into row format from column format. For ex: My log file login.lst contains the following SERVER1 DB1 SERVER2 DB2 SERVER3 DB3 SERVER4 DB4 I use awk to grep only the server... (6 Replies)
Discussion started by: senthil3d
6 Replies

9. Shell Programming and Scripting

column to row convert - script - help

Hi, I have a file named col.txt 1.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 I should get this 1.000 5.000 2.000 6.000 3.000 7.000 (10 Replies)
Discussion started by: G0Y
10 Replies

10. UNIX for Dummies Questions & Answers

convert column into row with some modifier

A file content have 1 1:-0.289433 2:0.833778 3:0.314471 4:-0.289433 5:-0.81876 6:-0.456693 7:-0.17511 8:-0.644555 9:-0.00666341 10:-1.13603 I will like to have that column into row with numbers to be printed (red color) only after colon output shud be like that -0.289433... (1 Reply)
Discussion started by: cdfd123
1 Replies

Featured Tech Videos