1

This is related to very interesting answer given here: Any text utility or hack to numbering poems lines omitting certain numbers?

awk 'FNR % 4 == 0 { printf "%6i %s\n", FNR, $0 ; next }; {printf "%6s %s\n", "", $0}' poem.txt

That does the job of numbering poem lines automatically.

However, in case we have several poems separated by blank lines, in this way:

    OF Mans First Disobedience, and the Fruit
    Of that Forbidden Tree, whose mortal tast
    Brought Death into the World, and all our woe,
    With loss of Eden, till one greater Man
    Restore us, and regain the blissful Seat,
    Sing Heav'nly Muse, that on the secret top
    Of Oreb, or of Sinai, didst inspire
    That Shepherd, who first taught the chosen Seed,


    In the Beginning how the Heav'ns and Earth
    Rose out of Chaos: or if Sion Hill
    Delight thee more, and Siloa's brook that flow'd
    Fast by the Oracle of God; I thence
    Invoke thy aid to my adventrous Song,
    That with no middle flight intends to soar
    Above th' Aonian Mount, while it pursues
    Things unattempted yet in Prose or Rhime.

I wonder if line numbering any four lines can be restarted after a blank space, in order to have:

    OF Mans First Disobedience, and the Fruit
    Of that Forbidden Tree, whose mortal tast
    Brought Death into the World, and all our woe,
 4  With loss of Eden, till one greater Man
    Restore us, and regain the blissful Seat,
    Sing Heav'nly Muse, that on the secret top
    Of Oreb, or of Sinai, didst inspire
 8  That Shepherd, who first taught the chosen Seed,


    In the Beginning how the Heav'ns and Earth
    Rose out of Chaos: or if Sion Hill
    Delight thee more, and Siloa's brook that flow'd
 4  Fast by the Oracle of God; I thence
    Invoke thy aid to my adventrous Song,
    That with no middle flight intends to soar
    Above th' Aonian Mount, while it pursues
 8  Things unattempted yet in Prose or Rhime.
    
1
  • 1
    So you need the numbers printed as 1-2 digits within the existing string of 4 blanks at the start of each input line, right?
    – Ed Morton
    Feb 4 at 14:14

3 Answers 3

1
$ awk '
    !NF { c=0 }
    NF {
        sub(/^ +/,"")
        $0 = sprintf("%2s  %s", (++c%4 ? "" : c), $0)
    }
1' file
    OF Mans First Disobedience, and the Fruit
    Of that Forbidden Tree, whose mortal tast
    Brought Death into the World, and all our woe,
 4  With loss of Eden, till one greater Man
    Restore us, and regain the blissful Seat,
    Sing Heav'nly Muse, that on the secret top
    Of Oreb, or of Sinai, didst inspire
 8  That Shepherd, who first taught the chosen Seed,


    In the Beginning how the Heav'ns and Earth
    Rose out of Chaos: or if Sion Hill
    Delight thee more, and Siloa's brook that flow'd
 4  Fast by the Oracle of God; I thence
    Invoke thy aid to my adventrous Song,
    That with no middle flight intends to soar
    Above th' Aonian Mount, while it pursues
 8  Things unattempted yet in Prose or Rhime.

or if you prefer:

$ awk -v RS= -F'\n' '
    NR>1 { print ORS }
    {
        for ( i=1; i<=NF; i++) {
            sub(/^ +/,"",$i)
            printf "%2s  %s\n", (i%4 ? "" : i), $i
        }
    }
' file
    OF Mans First Disobedience, and the Fruit
    Of that Forbidden Tree, whose mortal tast
    Brought Death into the World, and all our woe,
 4  With loss of Eden, till one greater Man
    Restore us, and regain the blissful Seat,
    Sing Heav'nly Muse, that on the secret top
    Of Oreb, or of Sinai, didst inspire
 8  That Shepherd, who first taught the chosen Seed,


    In the Beginning how the Heav'ns and Earth
    Rose out of Chaos: or if Sion Hill
    Delight thee more, and Siloa's brook that flow'd
 4  Fast by the Oracle of God; I thence
    Invoke thy aid to my adventrous Song,
    That with no middle flight intends to soar
    Above th' Aonian Mount, while it pursues
 8  Things unattempted yet in Prose or Rhime.
1

Using Raku (formerly known as Perl_6)

raku -e 'my @para = .split( /\n**2..*/, :skip-empty) given slurp; 
  @para = @para>>.lines>>.trim; for @para {for $_.kv -> $k,$v { 
  put ($k+1) %% 4 ?? sprintf("%6s  ", $k+1) ~ $v !! sprintf("%6s  ", "") ~ $v }; 
  "\n".put;}'  file

SAMPLE INPUT:

Paradise Lost, by John Milton (excerpted):

    OF Mans First Disobedience, and the Fruit
    Of that Forbidden Tree, whose mortal tast
    Brought Death into the World, and all our woe,
    With loss of Eden, till one greater Man
    Restore us, and regain the blissful Seat,
    Sing Heav'nly Muse, that on the secret top
    Of Oreb, or of Sinai, didst inspire
    That Shepherd, who first taught the chosen Seed,


    In the Beginning how the Heav'ns and Earth
    Rose out of Chaos: or if Sion Hill
    Delight thee more, and Siloa's brook that flow'd
    Fast by the Oracle of God; I thence
    Invoke thy aid to my adventrous Song,
    That with no middle flight intends to soar
    Above th' Aonian Mount, while it pursues
    Things unattempted yet in Prose or Rhime.

SAMPLE OUTPUT:

Paradise Lost, by John Milton (excerpted):

    OF Mans First Disobedience, and the Fruit
    Of that Forbidden Tree, whose mortal tast
    Brought Death into the World, and all our woe,
 4  With loss of Eden, till one greater Man
    Restore us, and regain the blissful Seat,
    Sing Heav'nly Muse, that on the secret top
    Of Oreb, or of Sinai, didst inspire
 8  That Shepherd, who first taught the chosen Seed,


    In the Beginning how the Heav'ns and Earth
    Rose out of Chaos: or if Sion Hill
    Delight thee more, and Siloa's brook that flow'd
 4  Fast by the Oracle of God; I thence
    Invoke thy aid to my adventrous Song,
    That with no middle flight intends to soar
    Above th' Aonian Mount, while it pursues
 8  Things unattempted yet in Prose or Rhime.

Above is an answer coded in Raku, a member of the Perl-family of programming languages. Briefly, the poem is slurp-ed in and split on any occurence of 2-or-more consecutive \n newlines, storing the data in the @para array (this essentially breaks the poem into 'paragraphs'). In the second statement >> hyper-operators are used to modify every element on the LHS with the function on the RHS. The @para>>.lines>>.trim chain is therefore read, "every element of `@para is coverted to lines (i.e. chomped) and every line of @para is converted to trimmed-lines".

In the next statement (a for loop), the @para array is iterated over. Immediately each (paragraph) element is converted to kv a key-value pair, and iterated over using a nested for loop, which implements Raku's ternary operator. Every occurrence of ($k+1) %% 4 if ?? True places $k+1 to the left of the $v verse, otherwise if !! False an "" empty-string is placed instead. Finally, @para are again separated by \n newlines.

https://raku.org

0

If your goal is to reset the counter only when there are at least two blank lines, then:

awk '{ if(/^$/&& pre==$0)c=0; else c++;
       pre=$0;
       printf "%6s %s\n", (c&&c%4==0?c:"") , $0
}' infile

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.