By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,848 Members | 1,416 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,848 IT Pros & Developers. It's quick & easy.

File Manuplation

P: 5
HI

I have a file named ctmlog which looks like this..

Expand|Select|Wrap|Line Numbers
  1. |0010 |     20081001 |  acgbhty   | runcnt  6 |
  2. |0011 |     20081001 |  acgbhty   | runcnt  7 |
  3. |0013 |     20081001 |  acgbhty   | runcnt  8 |
  4. |0010 |     20081001 |  fgthhhhh  | runcnt  1 |
  5. |0017 |     20081001 |  fgthhhhh  | runcnt  2 |
  6. |0019 |     20081001 |  fgthhhhh   | runcnt 3 |
I want to print only the last occurence of every jobname (ie fgthhhhh or acgbhty..so on) the output should look like

Expand|Select|Wrap|Line Numbers
  1. |0013 |     20081001 |  acgbhty   | runcnt  8 |
  2. |0019 |     20081001 |  fgthhhhh   | runcnt 3 |
Can anyone help me on this?

Cheers..
Antony
Jan 12 '08 #1
Share this Question
Share on Google+
8 Replies


eWish
Expert 100+
P: 971
Please provide the code that you have tried to get your desired results, so that we can help you.

--Kevin
Jan 12 '08 #2

P: 5
hi

new to perl. could you give me a frame of how to extract the result

thans
Jan 12 '08 #3

eWish
Expert 100+
P: 971
Read the datafile, split on '|' then compare the fields as you need, print your results.

Read perldoc.perl.org!

--Kevin
Jan 12 '08 #4

prn
Expert 100+
P: 254
prn
Hi Antony,

I'm not going to write the routine for you, but I do have some thoughts about the easiest way to handle it.

I also don't know how much data you are dealing with and it's possible that there is enough data there to make a difference. Assuming that you are dealing with no more than a few hundred to a few thousand lines of the format you described, this should work. It may not be the most efficient, but from what you are saying, I'm guessing that you are not going to be doing this in a real tight loop, so ease of writing is probably a higher priority than absolute efficiency.

First off, I suspect it's probably going to be easiest (conceptually) to work through the file in reverse order. Assuming (as above) that the file is not too big for in-memory manipulation, I'd just read in the whole thing,
Expand|Select|Wrap|Line Numbers
  1. open IN, $filename or die "Could not open $filename for input: $!\n";
  2. my @lines = <IN>;
  3. close IN;
and work backward by lines from the end of the array of lines.

As you check each line, if the jobname
Expand|Select|Wrap|Line Numbers
  1. my($foo,$bar,$baz,$jobname,$runno)=split (/|/,$_);
(array position 0 is before the first "|") is not one you have already encountered (create a hash of jobnames to keep track), then print the line to your output file. Otherwise drop it and go on to the next line.

That should cover the basic logic of the task.

Best Regards,
Paul
Jan 12 '08 #5

P: 5
Read the datafile, split on '|' then compare the fields as you need, print your results.

Read perldoc.perl.org!

--Kevin
Expand|Select|Wrap|Line Numbers
  1. $ctmhome="/pctrl/prodctrl/util_scripts";
  2. $ctmlogrpt="/pctrl/prodctrl/ctmserv/metrics/ctmlog";
  3. $ctmlogrpt_cleanrpt="/pctrl/prodctrl/ctmserv/metrics/ctmlog_cleanrpt";
  4. $ctmlog_byapp="/pctrl/prodctrl/ctmserv/metrics/ctmlog_byapp";
  5. $jobsbyapp="/pctrl/prodctrl/ctmserv/sql_scripts/output/jobappl.rpt";
  6.  
  7. # # # # # # #  Open Output file & Clean Up Control-M Log Reports  # # # # # # #
  8. #
  9. `rm $ctmlog_byapp`;
  10. open(OUTFILE, ">> $ctmlog_byapp");
  11. `grep "|" $ctmlogrpt > $ctmlogrpt_cleanrpt`;
  12.  
  13.  
  14. # # # # # # # Create New Control-M Log Report with Application Names  # # # # #
  15. # # #
  16. @ctmrpt=`cat $ctmlogrpt_cleanrpt`;
  17. foreach $rline (@ctmrpt) {
  18.   chomp($rline);
  19.   ($j,$rdate,$rtime,$jobname,$j,$j,$j,$message,$j) = (split(/\|/,$rline));
  20.   chomp($rdate);
  21.   chomp($rtime);
  22.   chomp($jobname);
  23. # remove leading / trailing blanks fromjobname
  24.   $jobname =~ s/^\s+//;
  25.   $jobname =~ s/\s+$//;
  26.  
  27. # add exactly 5 blanks to start of jobname
  28.    $jobname ="     ".$jobname;
  29.  
  30.   chomp($message);
  31.   ($j,$runcnt,$j) = (split("RUNCNT",$message));
  32.   chomp($runcnt);
  33.  
  34. if ($rdate eq "Date") {
  35.   next;
  36. }
  37.  
  38.   $appl=`grep $jobname $jobsbyapp`;
  39.   chomp($appl);
  40.   ($jbn,$application,$discard1,$discard2) = (split(" ",$appl));
  41.  
  42.   chomp($jbn);
  43.   chomp($application);
  44.  
  45.   $jbn_len=length($jbn);
  46.   $start_pos=($jbn_len - 1);
  47.   $last_letter=substr($jbn,$start_pos,1);
  48.  
  49.   if ($last_letter eq "F" || $runcnt > 2) {
  50.     next;
  51.   }
  52.  
  53.   printf OUTFILE ("%4s %4s %-15s %-25s %1s\n",$rdate,$rtime,$jobname,$applicatio
  54. n,$message);
  55.   #printf ("%4s %4s %-15s %-25s %1s\n",$rdate,$rtime,$jobname,$application,$mess
  56. age);
  57. }

i want to remove the filter and print everything , and if the run count is more than 2 then print the last count. how do i compare between fields jobname and run count
Jan 12 '08 #6

P: 5
Hi Antony,

I'm not going to write the routine for you, but I do have some thoughts about the easiest way to handle it.

I also don't know how much data you are dealing with and it's possible that there is enough data there to make a difference. Assuming that you are dealing with no more than a few hundred to a few thousand lines of the format you described, this should work. It may not be the most efficient, but from what you are saying, I'm guessing that you are not going to be doing this in a real tight loop, so ease of writing is probably a higher priority than absolute efficiency.

First off, I suspect it's probably going to be easiest (conceptually) to work through the file in reverse order. Assuming (as above) that the file is not too big for in-memory manipulation, I'd just read in the whole thing,
Expand|Select|Wrap|Line Numbers
  1. open IN, $filename or die "Could not open $filename for input: $!\n";
  2. my @lines = <IN>;
  3. close IN;
and work backward by lines from the end of the array of lines.

As you check each line, if the jobname
Expand|Select|Wrap|Line Numbers
  1. my($foo,$bar,$baz,$jobname,$runno)=split (/|/,$_);
(array position 0 is before the first "|") is not one you have already encountered (create a hash of jobnames to keep track), then print the line to your output file. Otherwise drop it and go on to the next line.

That should cover the basic logic of the task.

Best Regards,
Paul

hi
how to make the file in reverse order,
thanks
Jan 12 '08 #7

P: 33
After collecting all lines in the into an array use reverse function on the array as follows.
@array = reverse @array;

After this statement the array will consists of the elements in reverse order.
Jan 14 '08 #8

prn
Expert 100+
P: 254
prn
After collecting all lines in the into an array use reverse function on the array as follows.
@array = reverse @array;

After this statement the array will consists of the elements in reverse order.
That works just fine. Alternatively, just process the lines in reverse order, e.g.:
Expand|Select|Wrap|Line Numbers
  1. #! /usr/bin/perl
  2. use strict;
  3.  
  4. my $filename = 'test.txt';
  5. my $lineindex;
  6. my $line;
  7.  
  8. open IN, "<$filename" or die "Could not open $filename: $!\n";
  9. my @lines = <IN>;
  10. close IN;
  11.  
  12. print "The file had $#lines lines. \n";
  13.  
  14. print "Forward:\n";
  15. foreach $line (@lines) { print $line;}
  16.  
  17. print "\nReverse:\n";
  18. for ($lineindex=$#lines-1; $lineindex>=0; $lineindex--)
  19. {
  20.     print "Line $lineindex: $lines[$lineindex]";
  21. }
  22.  
Take your pick for how to do things. The perl motto is "There is more than one way to do it." TIMTOWTDI

HTH,
Paul
Jan 14 '08 #9

Post your reply

Sign in to post your reply or Sign up for a free account.