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

Sorry to re-submit this question again! Thank you for responding, nevertheless most of you may have assumed that each line is exactly 40 characters. That is not the case. I want to match lines in a block of text that
  1. Have 0-40 characters
  2. There can be from 0 - 4 lines in the block, but no more.

I need some help constructing a regular expression that can accomplish this. I have tried these 2 examples, but they dont work for me:

/(.{0,40}\n){0,4}/ /(?:.{0,40}\n){0,4}/m
The text is contained in a string, for example I would like to do this:

$foo = "1234567890123456789012345678901234567890 1234567890123456789012345678901234567890 1234567890123456789012345678901234567890 1234567890123456789012345678901234567890"; if ($foo =~ m/4 lines of 0 to 40 chars in length/) { do something }
Thanks again! Also, please no loops, the goal is to accomplish this with a single regex. If it is not possible, tell me. Cheers!

Robert

Replies are listed 'Best First'.
Re: How do I match lines of UP TO 40 chars BUT NO MORE in a block of text?
by Zaxo (Archbishop) on Sep 25, 2002 at 20:39 UTC

    In your prior post, lower processing time was the goal, not an artificial avoidance of loops not generated within the regex engine. See my reply Re: How do I match lines of 40 characters long in a block of text? for an efficient loop.

    Accepting that this is homework or a bar bet; if you must use a regex to decide that a block of text has fewer than five short lines, try to match five or more - failure is success:

    if ($foo !~ m/\A(?: #anchor start and group (?:.{41,}\n)* #maybe some long lines (?:.{0,40}\n) #one short line ){5,} #five or more (?:.{41,}\n)* #maybe some more long lines \z #anchor end /x ) { #do something }

    Update: Fixed link. Your first regex may work if you anchor the ends. It is matching long lines by backtracking to the -40 position from the newline.

    After Compline,
    Zaxo

Re: How do I match lines of UP TO 40 chars BUT NO MORE in a block of text?
by sauoq (Abbot) on Sep 25, 2002 at 20:26 UTC

    My reply at Re: How do I match lines of 40 characters long in a block of text? does what you want I think. Note that you don't really want to match 0 lines unless you want everything to match. Also, when you are constructing a regex, it is best to be able to state exactly what you want. I think you really want "1 to 4 lines each consisting of 0 to 40 characters followed by a newline." I've included the code from original reply below for your convenience.

    / ( # Assuming you want capture these lines. (?: # Group each line. ^ # Beginning of the line. .{0,40}\n # 0 to 40 characters followed by a newline. ){1,4} # 1 to 4 lines. (0 will permit an empty match.) ) # Done capturing. /mx; # /m so that ^ anchor works, /x for comments.
    -sauoq
    "My two cents aren't worth a dime.";
    
      Thanks! However this is not working for me! Here is my code:

      $foo = "line1line1line1line1line1line1line1line1 line2line2line2line2line2line2line2line2line2line2line2line2line2line2 +line2line2line2line2 line3line3line3line3line3line3line3line3"; if ($foo =~ /((?:^.{0,40})\n{1,4})/m) { print "$1: OK\n\n"; } else {print "$1: NOT OK\n\n";}

      I get this as a result: line1line1line1line1line1line1line1line1
      : OK

      Which is not good, since line2 is greater than 40 chars.

      thanks!

        Well, that's exactly what it should match. Your input matches your requirements. It has a block of text consisting of between 1 and 4 (1 in this case) lines of not more than 40 characters and an additional newline.

        Your requirements are poorly specified.

        Maybe, rather than see if your input matches such a block, you want to see if your input is such a block. If this is the case, your example input wouldn't work even if the second line had less than forty characters because your third line doesn't have a trailing newline.

        If that is what you are trying to do, try this:

        / ^ # Anchor to beginning of string. (?: # Group each line. .{0,40}\n # 0 to 40 characters followed by a newline. ){0,4} # 0 to 4 lines. $ # Anchor to end of string. /x; # /x for comments.
        -sauoq
        "My two cents aren't worth a dime.";
        
Re: How do I match lines of UP TO 40 chars BUT NO MORE in a block of text?
by BrowserUk (Patriarch) on Sep 25, 2002 at 21:49 UTC