🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.editors
Article #4043

Re: SED q. re multiline patterns (long)

#4043
From: G. Ioannou
Date: Sun, 22 Oct 1995 00:00
75 lines
3590 bytes
In article <DGtuuq.AJ@rci.ripco.com>, Eric Pement <epement@ripco.com> wrote:
[...]
>I want to remove a block of 4 contiguous lines which recur at repeated
>intervals throughout several files.  The first line of each block is
>always a blank line.  However, the input files also contain groups of 1
>or more blank lines which should not be deleted.  My problem arises when
>the block to be deleted is preceded by 1 or more blank lines.  E.g.,
>
>  1: aaa aaaa        # (Line numbers added for clarity)
>  2: bbb bbbb
>  3:
>  4:                 # Lines #4-7, inclusive,
>  5: xxxx            # should be deleted from
>  6: yyyy            # the input stream.
>  7: zzzz            #
>  8: ccc cccc
>  9: ddd dddd
>
[...]
>Since blank lines can appear anywhere in the input file, there may be
>two or even 3 blank lines before the deletion block.  I have tried
>writing other tests for the next two lines after a blank line, but the
>problem is that SED program logic jumps to the NEXT line read after the
>last "N" command rather than iterating on each line.

I think the following sed script should do the trick:

    :loop
    $b
    /^$/{
        N
        /\nxxxx$/b success
        P
        D
    }
    n
    b loop
    :success
    N
    N
    d

This script uses a technique I learned from Dale Dougherty's book,
`sed & awk', published by O'Reilly and Associates.  He calls this the
input/output loop, and explains it in the chapter on `Advanced Sed
Commands'.  The logic behind this is as follows:

The script is composed of two parts, the i/o loop and the success
routine.  As long as the current line is not blank, sed simply reaches
the n command, followed by an unconditional branch to the top of the
script, and therefore outputs the current line and starts from the
beginning with the next line.  As soon as a blank line is encountered,
the i/o loop is entered: the next line is appended to the pattern
space; if this line does not match xxxx, then the blank line is output
and then deleted (P then D).  The D command causes sed to start from
the beginning, USING THE LINE ALREADY IN THE PATTERN SPACE, NOT THE
NEXT LINE.  This is really the essence of the technique.

Now if the appended line matches xxxx, a branch is made to the success
label.  This appends the following two lines (yyyy and zzzz) and then
deletes the lot, from the blank line to zzzz inclusive.  The next line
is read in and sed starts from the beginning.

I have assumed that a blank line followed by xxxx is always a success,
in other words, that lines yyyy and zzzz always follow xxxx after a
blank.  If this is not true, then additional checking is needed in the
success routine.

I have put a `$b' command right after the :loop label, because
otherwise the script will not output the last line of input if it is
blank, presumably because the N command fails?  Anyway, this trick
seems to correct the problem.

Hope this helps.
-George.
Technical Details
Message-ID: <46e73i$5v7@lyra.csx.cam.ac.uk>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail
References: <DGtuuq.AJ@rci.ripco.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 107393,6054e8d9ed3d2572
X-Google-Attributes: gid107393,public
X-Google-Thread: 1025b4,6054e8d9ed3d2572
X-Google-Attributes: gid1025b4,public
From: gi101@cus.cam.ac.uk (G. Ioannou)
Subject: Re: SED q. re multiline patterns (long)
Date: 1995/10/22
Message-ID: <46e73i$5v7@lyra.csx.cam.ac.uk>
X-Deja-AN: 117934183
distribution: inet
references: <DGtuuq.AJ@rci.ripco.com>
organization: University of Cambridge, England
keywords: sed input/output loop
reply-to: gi101@cam.ac.uk
newsgroups: comp.editors,gnu.misc.discuss