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

Oh Wise Monks, I have to analyze a program written in an old, silly filetype where sections are separated by a long string of stars. I would like to improve readability by appending 4-digit decimal numbers to the ends of these lines. The appended numbers would count up from 0001 so that it is easy to know which grouping I am looking at without having to count myself. A script seems like an easy way to do this...can someone help me? Thanks, Jack
  • Comment on Numbering instances of a String in a file

Replies are listed 'Best First'.
Re: Numbering instances of a String in a file
by ikegami (Patriarch) on Jun 07, 2010 at 17:24 UTC

    It's extremely straightforward.

    • Initialise the count to zero.
    • While haven't reached the end of the file,
      • Read a line.
      • If the line consists of a bunch of stars,
        • Add 1 to the count.
        • Format the count.
        • Append formatted count to the line.
      • Print the line.

    What have you tried?

Re: Numbering instances of a String in a file
by toolic (Bishop) on Jun 07, 2010 at 17:24 UTC
    use strict; use warnings; my $cnt = 1; while (<>) { s/$/sprintf '%04d', $cnt++/e if /^\*+$/; print; }

    Update: The above code functionally satisfies the OP specification. Thanks to ikegami for demonstrating several optimization techniques below.

      Needless sprintf, needless match, and you should probably separate the number from the stars with a space. I'd also require at least 3 stars to trigger a match.

      my $cnt = '0000'; while (<>) { s/^(\*{3,})$/"$1 ". ++$cnt/e; print; }

      Optimised: (requires 5.10+)

      my $cnt = '0000'; while (<>) { s/^\*{3,}\K$/" ". ++$cnt/e; print; }

      As a one-liner: (Second version requires 5.10+)

      perl -pe'BEGIN { $cnt = '0000' } s/^(\*{3,})$/"$1 ". ++$cnt/e' perl -pe'BEGIN { $cnt = '0000' } s/^\*{3,}\K$/" ". ++$cnt/e'
        Without an eval:
        perl -ple 'BEGIN {$cnt = '0000'} $_ .= " " . ++$cnt if /\*{3,}$/'
Re: Numbering instances of a String in a file
by Anonymous Monk on Jun 07, 2010 at 19:12 UTC
    Oh great Perl Monks, I have tried a few of your solutions and they all do a very fine job of replicating the file, but they do not concatenate the numbers at all :-/ What could I be missing?
      This works for me in my linux shell:
      $ cat prog.pl use strict; use warnings; my $cnt = 1; while (<>) { s/$/sprintf '%04d', $cnt++/e if /^\*+$/; print; } $ $ $ cat file.txt foo boo *** goo hoo *********************************** bloo $ $ $ perl prog.pl file.txt foo boo ***0001 goo hoo ***********************************0002 bloo $
Re: Numbering instances of a String in a file
by Anonymous Monk on Jun 07, 2010 at 18:26 UTC
    wait first two people to answer, i'm confused. Where do you specify the filename?
      The perl community has a strong unix tradition. The programs above are written as filters and can be called on the command line as:

      perl mycode.pl < inputfile > outputfile
      or
      cat inputfile | perl mycode.pl > outputfile
      etc....
        Oh, and I forgot to mention, by the magic of the "<>" operator, the input file can just be mentioned as an argument to the program:
        perl mycode.pl inputfile > outputfile