Extracting a Range of Lines

Problem

You want to extract all lines from one starting pattern through an ending pattern or from a starting line number up to an ending line number.

A common example of this is extracting the first 10 lines of a file (line numbers 1 to 10) or just the body of a mail message (everything past the blank line).

Solution

Use the operators .. or ... with patterns or line numbers. The operator ... doesn’t return true if both its tests are true on the same line, but .. does.

while (<>) {
    if (/BEGIN PATTERN/ .. /END PATTERN/) {
        # line falls between BEGIN and END in the
        # text, inclusive.
    }
}

while (<>) {
    if ($FIRST_LINE_NUM .. $LAST_LINE_NUM) {
        # operate only between first and last line, inclusive.
    }
}

The ... operator doesn’t test both conditions at once if the first one is true.

while (<>) {
    if (/BEGIN PATTERN/ ... /END PATTERN/) {
        # line is between BEGIN and END on different lines
    }
}

while (<>) {
    if ($FIRST_LINE_NUM ... $LAST_LINE_NUM) {
        # operate only between first and last line, but not same
    }
}

Discussion

The range operators, .. and ..., are probably the least understood of Perl’s myriad operators. They were designed to allow easy extraction of ranges of lines without forcing the programmer to retain explicit state information. When used in a scalar sense, such as in the test of if and while statements, these operators return a true or false value that’s partially dependent on what they last returned. The expression left_operand .. right_operand returns false ...

Get Perl Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.