http://qs1969.pair.com?node_id=292854

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

a) in this $count = $data =~ m/and/; i have tried a way for the matching operator to count the occurences of the literal word 'and' inside the variable $data but it only gives me 1 every time. i also tried it with the global modifier /g but same thing here as well how may i write the above to actually count the occurences?

b) also i want to ask how can i take the next word after the matching pattern. in this particular exampel iwant to take the word after and each time and appears inside the variable $data.

c) One teacher of mine said to me that python is far more better than perl!?!? is this true? i hate to think so!!!

d) which tool may i use to make beautiful perl cgi web pages and then insert perl code where i want too? i tried dreamweaver but that one supports many client and server side languages except perl. Do you know of a tool that creates cgi perl output to helpome design pages? Carefull not html output but cgi perl output like Dreanweaver created php output when someone design a php web page.

Thanks thats all!

Edited by castaway: added formatting

Replies are listed 'Best First'.
Re: a Couple of questions!
by bart (Canon) on Sep 20, 2003 at 14:11 UTC

    a) There's a recent thread here (I think in meditations, "Perl idioms explained", but I'll look it up for you) that explains what happens with // and //g. In short: you need to use //g in list context, and extract the count from there.

    $count = () = $data =~ m/and/g;

    Update: Got it: Perl Idioms Explained - @ary = $str =~ m/(stuff)/g

    b) Even if it's another "and"? Use lookahead.

    my($next_word) = /and(?=\W*(\w+))/;
    You can use list context again, in which case you'll get a list of list of matches, but flattened.
    my @pairs = /(and)(?=\W*(\w+))/g;
    Test script:
    $_ = 'foo and bar and baz went to the sea.'; my @pairs = /(and)(?=\W*(\w+))/g; print join "#", @pairs;
    Result:
    and#bar#and#baz

    c) That's just his point of view. Tastes vary. I happen to disagree. But that's just me. :)

    d) Dunno. Maybe you should try out one of those template modules. That way you can separate code (script) from design (template). There's a nice list in the intro chapter of the Mason book: chapter 1

    There's also a comparative list in this article on <perl.com>: Choosing a Templating System

      Can you please explain a) and b) more detailed please? i tried out yous answer of a) which is
      $count = @count = $data =~ m/and/g; and it works ok
      also this works as well
      $count = () = $data =~ m/and/g;
      The problem is that i don't seem to understand why they are working!!! can u please expalin a liitle bit more? as far as for b) is this
      $_ = 'foo and bar and baz went to the sea.'; @pairs = /(and)(?=\W*(\w+))/g; print join "#", @pairs;
      the same as this?
      $data = 'foo and bar and baz went to the sea.'; @pairs = $data =~ /(and)(?=\W*(\w+))/g; print "@pairs";
      i dont understand this line of yours!
      @pairs = /(and)(?=\W*(\w+))/g;
      do you mean this?
      @pairs = $data =~ /(and)(?=\W*(\w+))/g;
      is $data implied on this? and what about the w the * and the +?

      edited: Sat Sep 20 15:00:09 2003 by jeffa - code tags

        First off Nik, please start using code tags and making your posts look nice in general. When you post something to this site, you are suppose to click the PREVIEW button first - don't click SUBMIT until the posts looks good. How do you make a post look good? By using our Perl Monks Approved HTML tags and reading over Writeup Formatting Tips first. I have looked at your previous posts and see that you have never learned this simple, important step for getting good information and respect from this community.

        If you want to understand the code you have been given, please try to do a little research on your own. A good perldoc page to read is perlre, this contains every answer to all of your regex questions.

        What is hard to understand, however, is this:

        $count = () = $data =~ m/and/g;
        so let's break it down. Hopefully, you realize that $data =~ m/and/ is a boolean test. It just asks "does $data contain the word 'and'?". If it does, then the answer to the question is true. If it does not, then the answer to the question is false. However, we don't want to know if 'and' appears or not, we want to count how many times it does appear.

        Hopefully you also know about the 'g' modifier. This allows us to match the pattern more than once. Of course, in our simple version above, 'g' is not needed because we only ask if 'and' appears or not - the number of times is irrelevant.

        This finally brings us to "scalar context" versus "list context" (see perldata). As you found out in your original question, this does not work:
        $count = $data =~ m/and/g;
        Because we ask the question in "scalar context", we get back ... true (assuming $data does contain 'and'). In order to actually count the occurances, we have to explicitly tell Perl that we want "list context". This is why we have the bare parens (an empty list) in between $count and $data. If you still don't understand, don't worry -- this took me a few months to understand. :)

        The rest of your questions are all addressed in perlre. I would answer them now, but since you didn't use code tags ... i will instead instruct you to go do some reading. And next time, please for the love of God use code tags man.

        Oh, and as for Python versus Perl ... what do you think we are going to say? This is a Perl site! :P

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: a Couple of questions!
by jonadab (Parson) on Sep 20, 2003 at 14:40 UTC
    $count = $data =~ m/and/; i have tried a way for the matching operator to count the occurences

    I don't think the ordinary match operator (m//) does that. I think it just returns true (it matched) or false (no match) in scalar context. In list context, though, it will return a list consisting of the last item matched by each set of parens, which still isn't what you want, since you want to know how many times a given set of parens matched. However, if you have no parens, then I think it returns a list of all the matches of the whole string. If you assign that to an array, *then* evaluate it in scalar context, you should be able to get a count.

    my @matches = $data =~ m/and/; my $count = scalar @matches;

    Or, more tersely...

    my $count = @{[$data=~m/and/]}
    i also tried it with the global modifier /g

    You could do that in a loop (see below). Note that s///g and m//g do slightly different things.

    For counting individual characters, it is generally considered that tr/// is the fastest way, but of course that won't work for something several chars long. There are, of course, other ways to accomplish what you want...

    You can get a good approximation with split...

    my $count = (scalar split /and/, $data) -1;

    One problem with this approach is that it uses extra memory temporarily; if your string is really really long, that could be an issue. (For a string of any sane length, though, it won't matter.) Also, it causes copying of most of the content of the string (again, temporarily), so if this is going to happen many many times in a nested loop it could perform badly. Perhaps the worst problem is that if your pattern (in the example, /and/) matches at the beginning or end of the string that will throw your count off by one.

    There are other ways to do it. For example, you could go back to using m//g in scalar context after all; it returns true once for each match, and you can count by incrementing a pointer.

    my $count=0; while ($data=~m/and/g) { ++$count }

    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: a Couple of questions!
by jonadab (Parson) on Sep 20, 2003 at 15:00 UTC
    which tool may i use to make beautiful perl cgi web pages and then insert perl code where i want too?

    Perl or no Perl, if you want beautiful pages you'll write them by hand (possibly using an editor with helps, such as cperl-mode in Emacs). The automatic page generation tools (Dreamweaver, Frontpage, Composer, and their ilk) invariably produce very messy code, code that's not maintainable, code that's needlessly bloated, code that's impossible for a human to read if you need to look at it to debug a problem, code that relies so extensively on physical markup (e.g., font tags) that you must abandon all pretense of accessibility, code that won't validate in a billion years, code that relies so heavily on browser quirks that when the next versions of the major browsers come out it will probably break and you'll have to redo it all. The advantages of these tools mostly involve people who don't know very much HTML being able to whip up a bunch of pages quickly. There's nothing beautiful about the results.

    My advice if you want to make beautiful pages is to read one of the w3schools tutorials, which will take you all of an hour, get a text editor with good syntax highlighting and automatic indentation, and write the pages by hand. Bonus points if your editor will automatically insert the close tag together with the open tag; this helps greatly in keeping your code wellformed. Oh, and a graphic design course won't hurt, too.

    As far as inserting the Perl code, there are two ways to go. You can use embperl, or you can make the whole page a Perl script, sticking the HTML in strings or HERE documents that the script prints. The latter approach is the one I use.

    update: Templates are on my list of things I intend to evaluate; my recommendation should not be taken as advice against using templates.


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/

      Great advice, but i have a couple of nitpicks:

      I start off with Dreamweaver ... but i don't maintain with Dreamweaver. Big difference. The advantage here has nothing to do with how much knowledge of HTML i have, but instead how much drudgery i don't want to type myself. Making a table is so much easier with the mouse, and the resulting HTML can always be filtered through HTML Tidy if i don't like it.

      You forgot to mention a third way: seperate your Perl code from the HTML. This is where HTML::Template and Template rule. I no longer use those gruffy looking HERE docs for HTML.

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      B--B--B--B--B--B--B--B--
      H---H---H---H---H---H---
      (the triplet paradiddle with high-hat)
      
        Making a table is so much easier with the mouse

        With a decent editor1, this is simply not true. A few lines of lisp in your configuration go a *long* way toward reducing the amount of typing you have to do. In cperl-mode (with my custom enhancements in the hook), I hit one keystroke for my insert-tag function, type in table, hit Enter, and the following is inserted:

        <table width=\"100%\"><thead> <tr><th></th></tr> </thead><tbody> <tr><td></td></tr> </tbody></table>
        And it leaves my cursor positioned inside the th. Similar shortcuts exist for other common tasks. My fingers never have to leave the keyboard.


        1 -- By <q>a decent editor</q> I of course mean Emacs, but this is not intended to start an editor war; feel free to customise your editor of choice in a similar fashion, if it provides the facilities for you to do so.

        $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
        what exaclty is a template and how can i use it?
      thanks man! i try the here document way myself too!
Re: a Couple of questions!
by archen (Pilgrim) on Sep 21, 2003 at 01:39 UTC
    c) One teacher of mine said to me that python is far more better than perl!?!?

    Is this a college level professor? Every language has it's pros and cons. I really doubt any language qualifies as a much better than any other, although there are a few that come to mind, and there are others that are just inherently a mess. Despite the fact that I absolutely hated the Prologue and Lisp programs I wrote in college, I have to admit that they have their place, and certainly have advantages in many respects.

    Now if (s)he were just taking a jab at Perl there really isn't anything wrong with that, hell I do it with Fortran all the time, but anyone who seriously believes one language is "far better" than another is probably not a very seasoned programmer.
Re: a Couple of questions!
by eyepopslikeamosquito (Archbishop) on Sep 21, 2003 at 04:25 UTC
    c) One teacher of mine said to me that python is far more better than perl!?!?

    Your teacher is a moron. I remember my teacher telling us that Pascal is far more better than C. Perl and Python (and Ruby) are very similar languages, each with its own strengths and weaknesses. To proclaim any one of these as "far more better" is a breathtaking display of arrogance, it being largely a matter of taste (though I prefer Perl to Python).

      I'd have problems with a teacher that used the phrase "far more better" just from the abuse of English.

      Having taught some programming in my time, I will say that Pascal is better than C --- as an initial teaching language.

      From there you can happily go down to Asm or up to ruby/python as a next step. Or go to C and start teaching more complicated aspects. Pascal makes a pleasant introduction to many of the useful base concepts of programming.