Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Group __DATA__ lines in a while?

by Lady_Aleena (Priest)
on Oct 21, 2013 at 05:22 UTC ( [id://1059065]=perlquestion: print w/replies, xml ) Need Help??

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

Update: I'm putting this update at the top because this is a longish post. I think I got it, and I put how I got it in a reply below. Sometimes I just have to type what I want out to get some perspective.

Hello. I am looking for pointers for the best way to group __DATA__ lines while looping them through a while to create sections. In the sample data below, the first three lines are the lede, which I would like to be the first section. The fourth line starts with a 2 which indicates the first section header. I would like to group the header and the lines following until the next line which starts with a 2 in a section. I would run each section through the while in story. Not all stories have headings, so a whole story might be one section; not all stories have ledes, so the first section may have a heading. I don't know if this is a good idea, but maybe have a way to do a quick pass through the data looking for lines which start with 2, if there aren't any, just run it through without separating it into sections.

While I am at it, I would also like to grab all the lines which start with a 2 to print a table of contents if there are 3 or more headings. Maybe the two things can be done at the same time?

story is the most used subroutine after html on my site, so I'm starting with it first. I'm updating my styles, which means I need to divide my stories up.

Here is what I have.

sub story { my ($source,$author) = @_; my $tab = 3; while (my $line = <$source>) { chomp($line); # If a line starts with a bracket, just print the line. if ($line =~ m/^</) { line($tab,$line); } # If a line starts with a numeral 1-6, print a heading. elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); my $id = idify($text); heading($tab,$heading,$text, { id => $id }); } # If a line is a break or horizontal rule, print the line in brack +ets. elsif ($line =~ /^[bh]r$/) { line($tab,"<$line>"); } # All other lines are paragraphs. else { paragraph($tab,$line); } } # If I wrote a story, I want people to know I wrote it at the bottom +. paragraph($tab,"written by $root_user", { class => 'author' }) if !$ +author; }

Here how to use the above (with a few other things).

#!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib 'files/lib'; use Base::HTML qw(html story); html( code => sub { story(*DATA,'me') });

And here is sample data.

__DATA__ I was born on July 10th, 1971 at Fort George G. Meade, Maryland. ... I use Mozilla Firefox to browse the internet with Google as my p ... When I was younger, I was simultaneously interested in astronomy ... 2 This site About a decade ago, I got 10 megabytes of complimentary web spac ... At first I found a site here and there which told me what all th ... It took some very patient people talking me through my hysterics ... Let's pause for a moment. At the time the only browser on my com ... The main issue causing my headaches was my frames looked bad in ... After telling someone I use SSI on my site, I was told Perl woul ... 2 Pets We love cats. We have a cat named Cache. Before Cache, we had a ... 2 Colors I do not have one favorite color but prefer shades of blue and y ... 2 Birthstones and the Zodiac My birth stone is the ruby and birthday stone is sapphire. My bi ... 2 Preferred user names I have used many user names over the years. There are so many on ... 3 Fantasy Fantasy is my favorite genre so when it came time to pick a CB h ... 3 Lady Aleena - a story A woman sat at the keyboard of her computer and was posting on a ... Years later she started to play Dungeons and Dragons. She was cr ... Not long after that, she found Excite.com. She needed a user nam ... 4 Aleena, the Overpower of Afa <i>This was written by a man I know only as Thraymire not by me ... From the nothingness <span style="color:#009">that encompassed a ... The powers beseeched the Goddess for the boon of creating life o ... "You have desired worshipers. You now have them, but also now mu ... And so, each creation was given knowledge a little at a time, an ... So time marched on, with the different creations on the world of ... From without Afa came a mortal messenger, a worshipper of a powe ... But the world of Afa could not take the tremendous strife. Conti ... To her bickering children, the Goddess announced, "Long have I w ... The Goddess descended to the Isle of the Goddess, but the powers ... <span style="color:#009">The Goddess took some of the portfolio ... <span style="color:#009">She sits on her throne in what appears ... <span style="color:#009">There is no official church for Aleena ... 3 Lady Aerianna I only use this handle on Yahoo! since Lady Aleena was already t ... 3 Lady Olara I only used this handle on Hotmail since Lady Aleena was already ... 2 Favorite quotes <blockquote>"A man's knowledge is like an expanding ...</blockquote> <blockquote>Do to others as you would have them do ...</blockquote> <blockquote>An it harm none, do what ye will. — Wic ...</blockquote> 3 My quotes <blockquote>"The stupid question is the question un ...</blockquote> <blockquote>"Sticks and stones may break my bones, ...</blockquote> <blockquote>"Nothing is ever complete until all mat ...</blockquote>

If you want to read the full text, go to my About page. :)

No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re: Group __DATA__ lines in a while?
by hdb (Monsignor) on Oct 21, 2013 at 05:53 UTC

    Not quite sure what you are looking for as your code seems to be doing what you want. As per your table of contents, you could push each $line (or [ $heading, $text ]) onto some array @toc whenever you encounter a heading and format it when you are through with all the data.

      I would like to wrap each section in an HTML <section>. Also, the subroutines (line, heading, and paragraph) used in story print immediately. It appears to get the table of contents, I will have to go through the lines twice.

      sub story { my ($source,$author) = @_; my $tab = 3; my @toc; while (my $line = <$source>) { chomp($line); if ($line =~ /^2/) { my ($number,$text) = split(/ /,$line,2); push @toc, anchor($text, { href => '#'.idify($text) }); } } list($tab, 'u', \@toc, { class => 'two' }); # I ran $source above, so I can't have it here! /me head desks. while (my $line = <$source>) { chomp($line); # If a line starts with a bracket, just print the line. if ($line =~ m/^</) { line($tab,$line); } # If a line starts with a numeral 1-6, print a heading. elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); my $id = idify($text); heading($tab,$heading,$text, { id => $id }); } # If a line is a break or horizontal rule, print the line in brack +ets. elsif ($line =~ /^[bh]r$/) { line($tab,"<$line>"); } # All other lines are paragraphs. else { paragraph($tab,$line); } } # If I wrote a story, I want people to know I wrote it at the bottom +. paragraph($tab,"written by $root_user", { class => 'author' }) if !$ +author; }
      No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
      Lady Aleena

        How about delayed execution? You push all commands onto a stack and only execute after reading all data:

        sub story { my ($source,$author) = @_; my $tab = 3; my @toc; my @commands; push @commands, [ \&startsection, "Lead" ]; # I ran $source above, so I can't have it here! /me head desks. while (my $line = <$source>) { chomp($line); # If a line starts with a bracket, just print the line. if ($line =~ m/^</) { push @commands, [ \&line, $tab, $line ]; } # If a line starts with a numeral 1-6, print a heading. elsif ($line =~ /^[1-6]\s/) { my ($heading,$text) = split(/ /,$line,2); if( $heading == 2 ) { push @toc, anchor($text, { href => '#'.idify($text) } +); if( $commands[-1]->[0] eq \&startsection ) { # not sur +e this comparison is valid... pop @commands; # to avoid empty sections } else { push @commands, [ \&endsection ]; } push @commands, [ \&startsection, $text ]; # adapt arg +uments as required } my $id = idify($text); push @commands, [ \&heading, $tab,$heading,$text, { id => +$id } ]; } # If a line is a break or horizontal rule, print the line in b +rackets. elsif ($line =~ /^[bh]r$/) { push @commands, [ \&line, $tab, "<$line>" ]; } # All other lines are paragraphs. else { push @commands, [ \&paragraph, $tab, $line ]; } } push @commands, [ \&endsection ]; # do the table of contents list($tab, 'u', \@toc, { class => 'two' }); # delayed execution of all print commands for (@commands) { my $cmd = shift @$_; $cmd->(@$_); } # If I wrote a story, I want people to know I wrote it at the bott +om. paragraph($tab,"written by $root_user", { class => 'author' }) if +!$author; }

        I cannot test this code but it hopefully conveys the idea...

        startsection and endsection would be two subs to print the HTML to start and end a section.

        Update: some changes in formatting of the post and added a missing comma in the code.

        Update: added a missing endsection at the end.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-19 22:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found