Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

perl file formatting

by perlforsgs (Initiate)
on Dec 23, 2016 at 08:37 UTC ( [id://1178418]=perlquestion: print w/replies, xml ) Need Help??

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

Hi everyone,

I was working on a perl file conversion for the below logic:

Sample input:

... F12 F11 F481 F55 F989 8204 20160930 1064.848 test Y 8204A 20160930 1064.505 test Y 8204B 20160930 1045.469 test Y

First rows are headers with value below.We need to convert this data into such a way that the data repeats from the date column under F11 till the day on which we are processing the file .Assume we are processing file on 20161002’,then the data file out will be as below.

F12 F11 F481 F55 F989 8204 20160930 1064.848 test Y 8204A 20160930 1064.505 test Y 8204B 20160930 1045.469 test Y 8204 20161001 1064.848 test Y 8204A 20161001 1064.505 test Y 8204B 20161001 1045.469 test Y 8204 20161002 1064.848 test Y 8204A 20161002 1064.505 test Y 8204B 20161002 1045.469 test Y

Any ideas please

Replies are listed 'Best First'.
Re: perl file formatting
by hippo (Bishop) on Dec 23, 2016 at 09:41 UTC
    Any ideas please
    1. Write tests - lots of them. Dates are tricky, illogical things (months have varying numbers of days, timezones affect what the current date is, remember about leap years, etc.).
    2. Construct an algorithm to produce the desired output.
    3. Code up the algorithm.
    4. Run the tests and adjust the code and/or algorithm until they all pass.

    Which specific part of all this are you having trouble with?

Re: perl file formatting
by poj (Abbot) on Dec 23, 2016 at 09:30 UTC
    Any ideas please

    Maybe use Time::Piece to generate the added days.

    #!perl use strict; use Time::Piece; use Time::Seconds 'ONE_DAY'; my $process_date = '20161002'; my $t = Time::Piece->strptime($process_date,"%Y%m%d"); #my $t = Time::Piece->new(); # today print "Process date is ".$t->ymd('')."\n"; my $data_date = '20160930'; my $d = Time::Piece->strptime($data_date,"%Y%m%d"); print "Date in data is ".$d->ymd('')."\n"; $d += ONE_DAY; while ($d <= $t){ print " Add date ".$d->ymd('')."\n"; $d += ONE_DAY; }
    poj
Re: perl file formatting
by Corion (Patriarch) on Dec 23, 2016 at 08:39 UTC

    What code have you already written and where are you encountering problems?

    I assume that your input data will either be space delimited or fixed width, so split or unpack might be of help. For bringing the data in date order, sort will likely help. For filtering the data for the report run date, see grep.

    Usually, it helps us help you much better if you post an SSCCE as a starting point for the discussion. That shows us where you are and allows us to give you much better directions on how to get to where you want to be.

Re: perl file formatting
by tybalt89 (Monsignor) on Dec 23, 2016 at 17:34 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1178418 use strict; use warnings; sub eightdigitdate { my @fields = localtime(shift); sprintf '%04d%02d%02d', $fields[5] + 1900, $fields[4] + 1, $fields[3 +]; } sub nextday { use Time::Local; shift() =~ /(\d{4})(\d\d)(\d\d)/; eightdigitdate( 60*60*24 + timelocal 0, 0, 12, $3, $2 - 1, $1 ); } #my $today = eightdigitdate(time); my $today = '20161002'; print scalar <DATA>; print my @data = <DATA>; my $more = 1; while($more) { for(@data) { my $date = (split)[1]; if( $date < $today ) { s/\b$date\b/ nextday($date) /e; print; } else { $more = 0; } } } __DATA__ F12 F11 F481 F55 F989 8204 20160930 1064.848 test Y 8204A 20160930 1064.505 test Y 8204B 20160930 1045.469 test Y
      Tried something like this But couldnt get the required ,Any help APPRECIATED
      #!/usr/bin/perl my $isHeader = 1; my $targetDate = 20161002; foreach (<STDIN>){ if (!$isHeader){ my ($M12,$M11,$M481,$M55,$M989) = split(' ',$_); if ($M11 <= $targetDate){ print $_; } } $isHeader = 0; }

        Are your input data columns really separated by a space? In the sample above it looks like it may be tabs, in which case your regexp won't match. Maybe try:

        split(/\s+/, $_);

        Hope this helps!


        The way forward always starts with a minimal test.
        #!/usr/bin/perl # http://perlmonks.org/?node_id=1178418 use strict; use warnings; sub eightdigitdate { my @fields = localtime(shift); sprintf '%04d%02d%02d', $fields[5] + 1900, $fields[4] + 1, $fields[3 +]; } sub nextday { use Time::Local; shift() =~ /(\d{4})(\d\d)(\d\d)/; eightdigitdate( 60*60*24 + timelocal 0, 0, 12, $3, $2 - 1, $1 ); } #my $today = eightdigitdate(time); my $today = '20161002'; print scalar <STDIN>; print my @data = <STDIN>; my $more = 1; while($more) { for(@data) { my $date = (split)[1]; if( $date < $today ) { s/\b$date\b/ nextday($date) /e; print; } else { $more = 0; } } }
Re: perl file formatting
by Marshall (Canon) on Dec 23, 2016 at 09:06 UTC
    Your post is incomprehensible due to the formatting.
    Please enclose fixed field stuff within <code>...</code> tags. That will show where one line ends and another begins.

    See Markup in the Monastery for description of other tags.

    Update: I see that you updated the code tags. Thanks!
    Another Perl module to consider is Date::Time.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-25 21:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found