in reply to How do I match lines of 40 characters long in a block of text?

if ($foo =~ m/(?:.{0,40}\n){0,4}/m) { print "ok" }

/m is for "multi-line" match

update: see bart below for why is this wrong . See sauoq answer instead.

update: now I've got it (I did learn something today!) :

The RE is:  /((?:[^\n]{0,40}\n){0,4})/

or:  /((?:.{0,40}\n){0,4})/     # thanks sauoq!

roughly meaning: group( (up-to-40 non-line-breaks, line-break) up-to-4 times)close-group

Test code:

$line = "x" x 38 . "\n"; sub test { ($res) = ($_[0] =~ /((?:[^\n]{0,40}\n){0,4})/); if ($res) { print "yes\n"; } else { print "no\n"; } } test( "x$line" x 4 ); # 39 x 4 test( "xx$line" x 4 ); # 40 x 4 test( "xxx$line" x 4 ); # 41 x 4 test( "xx$line" x 3 ); # 40 x 3 test( "x$line" x 5 ); # 39 x 5

output:

yes yes no yes yes

Thanks thelenm and BrowserUk. sauoq got something very similar too.

sauoq noted that  [^\n] is the same as a "dot".

Replies are listed 'Best First'.
Re: Re: How do I match lines of 40 characters long in a block of text?
by BrowserUk (Patriarch) on Sep 25, 2002 at 19:08 UTC

    Won't that match 0 to 4 lines of (0 to 40 characters + nl)?

    Update:Of course it wil, cos that's what he asked for! D'oh!


    Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
      I'm still curious why he would want to match zero lines. I'd expect him to want to match at least one line.

      And: as soon as you ask for at least one line, without an "^" anchor, your first line might contain more than 40 characters, only the regex it will only grab the last 40 ones of that line!

      In short: it is definitely not a bad idea to add an anchor.

      /^((?:.{0,40}\n){0,4})/;
      or
      /^((?:.{0,40}\n){1,4})/m;
      The latter case can grab 1 to 4 whole lines anywhere in your text.

        Agreed bart, I'm not sure that the OP has clearly stated his req's or perhaps he doesn't have a clear picture of what his req's are.

        I agree with you about the need for anchors, but despite using either /m or /s, I couldn't get things to work with just that. I ended up using \A which worked better, but on its own didn't seem to be enough. I also played with using $, \Z and \z, but I admit I am still a little confused about quite what each does in the contexts of /s and /m. Something I need to play with more.


        Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!

      Sure!

      I want to match up to 4 lines of up to 40 characters of text each

        Though yours will match 4 lines of 41 chars (or 5 of 77 infact) as well.


        Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
Re: Re: How do I match lines of 40 characters long in a block of text?
by thelenm (Vicar) on Sep 25, 2002 at 19:20 UTC
    The /m modifier only changes the behavior of "^" and "$" (whether they match at embedded newlines). Since your regex doesn't use either of those, the /m has no effect.

    -- Mike

    --
    just,my${.02}

Re: Re: How do I match lines of 40 characters long in a block of text?
by sauoq (Abbot) on Sep 25, 2002 at 20:13 UTC

    Your update isn't really any different than your first crack at it. A dot is equivalent to your character class, [^\n], as long as there is no /s modifier on the regex. A dot means "match any character except for a newline."

    -sauoq
    "My two cents aren't worth a dime.";