Seeking critique of simple file line numbering code.

Ask a Question related to PERL Miscellaneous, Design and Development.

  1. #1

    Default Seeking critique of simple file line numbering code.

    I realize that grep performs some of this same functionality, but I just
    wanted to create the tool on my own for the experience. To that end, I'm
    also interested in hearing how I might clean it up from every standpoint
    (style, robustness, etc.). This script reads infile, prepends a line number
    to each line in the file, and outputs it as outfile. Come to think of it, I
    probably should have just written the output to stdout to make it easier to
    redirect from the shell. But this is just for discussion's sake.

    It's pretty basic, and the comments within the file should tell what's going
    on.

    #!/usr/bin/perl

    # Usage:
    # linenum [-s] infile [outfile]

    # linenum writes outfile with line numbers prepended
    # to each line in infile.

    # The -s flag causes line numbers in the format of /^d+:/
    # to be stripped. Use -s to un-do what was done
    # by linenum.


    use strict;
    use warnings;


    # Strip and save command line switches.

    my @switch;
    foreach ( @ARGV ) {
    if ( $_ =~ /^-(.)/ ) {
    push @switch, $1;
    shift @ARGV;
    }
    }



    # Check for -s switch.

    my $remove_numbers = 0;
    foreach ( @switch ) {
    if ( $_ eq "s" ) {
    $remove_numbers = 1;
    } else {
    print "Invalid option, -$_.\n";
    print "Usage: linenum.pl [-s] infile [outfile]\n";
    exit;
    }
    }


    # Pull in the filenames.

    my ( $infile, $outfile ) = @ARGV;


    # If outfile wasn't specified, make up a name.

    $outfile = $outfile || $infile.".out";

    # Test for file existances.

    unless ( -e $infile ) {
    print "$infile doesn't exist.\n";
    print "Exiting.\n";
    exit;
    }

    if ( -e $outfile ) {
    print "$outfile already exists\n";
    print "Overwrite? [Y/N]: ";
    if (my $decision = <STDIN> !~ /^[yY]/) {
    print "Aborting.\n";
    exit;
    }
    }



    # Open the files.

    open ( INFILE, "<$infile" ) or
    die "Unable to open $infile.\n$!";

    open ( OUTFILE, ">$outfile" ) or
    die "Unable to open $outfile.\n$!";


    # Start the counter, and process the files.

    my $count = 0;
    while ( <INFILE> ) {
    # If the remove_numbers flag isn't set,
    # increment the counter, prepend number.
    unless ( $remove_numbers ) {
    $count++;
    $_ = "$count: ".$_;
    } else {
    # Otherwise strip number prefixes.
    $_ =~ s/^\d+://;
    }
    print OUTFILE $_;
    }

    # Sweep up, turn out the lights, lock the
    # door on the way out.
    close ( INFILE ) or
    die "Unable to close $infile.\n$!";

    close ( OUTFILE ) or
    die "Unable to close $outfile.\n$!";




    --
    DJO


    David Oswald Guest

  2. Similar Questions and Discussions

    1. simple code help with streaming 1 file
      I set up the Flash Media Server 2.0 on Windows (test box) under the host dl35.tamu.edu (behind a firewall so I don't mind giving it out) Under the...
    2. I cna't see the problem... on simple 25 line of code
      what am trying to do is to get it to send some vars to a HTTPSerivce using the "POST" method and I wanted to try the basics out before I started...
    3. Wanted - Simple section numbering prog for HTML document
      I maintain various specs and FAQs in manually edited HTML documents, and I'd very much like some simple way of automatic section numbering as in...
    4. Seeking advice on selecting a sub (possibly/slightly related to cmd line switches)
      I'm not sure the subject line is appropriate. Couldn't come up with anything better... Well, just to be definite (but not limited to the...
    5. C# Equivalent of VB.Net Code -- One line of code, simple
      Great idea, thanks. I only need something simple in order for my contact form to work correctly. It's nothing with a lot of overhead. Ron...
  3. #2

    Default Re: Seeking critique of simple file line numbering code.

    >>>>> "DO" == David Oswald <spamblock@junkmail.com> writes:

    DO> use strict;
    DO> use warnings;

    good start

    DO> # Strip and save command line switches.

    DO> my @switch;
    DO> foreach ( @ARGV ) {
    DO> if ( $_ =~ /^-(.)/ ) {

    no need for $_ as it is the default bound value for m//

    DO> push @switch, $1;
    DO> shift @ARGV;
    DO> }
    DO> }

    bad switch handling. either use a standard module or a cpan one. perl
    even has simple switch handling with the -s option (see perlrun) but you
    would have to deal with a package global that way.

    DO> # Check for -s switch.

    DO> my $remove_numbers = 0;
    DO> foreach ( @switch ) {
    DO> if ( $_ eq "s" ) {
    DO> $remove_numbers = 1;
    DO> } else {
    DO> print "Invalid option, -$_.\n";
    DO> print "Usage: linenum.pl [-s] infile [outfile]\n";

    use a here doc to print multiple lines. that way you see what you get
    and you lose the quotes and\n noise.

    DO> exit;
    DO> }
    DO> }

    blech. again, a standard arg parsing module is best. the good ones work
    with a hash ref so you can keep strict clean. then you have 2 lines, one
    to call the module and one to set $remove_numbers from $opts{'s'}.


    DO> # Pull in the filenames.

    DO> my ( $infile, $outfile ) = @ARGV;


    DO> # If outfile wasn't specified, make up a name.

    DO> $outfile = $outfile || $infile.".out";

    $outfile ||= "$infile.out";

    DO> # Test for file existances.

    DO> unless ( -e $infile ) {
    DO> print "$infile doesn't exist.\n";
    DO> print "Exiting.\n";

    here doc to the rescue again. multiple prints in a row are fugly and slower.

    DO> exit;

    why not call die with the error message?

    -e $infile or die <<DIE ;
    $infile doesn't exist.
    Exiting.
    DIE


    DO> if ( -e $outfile ) {
    DO> print "$outfile already exists\n";
    DO> print "Overwrite? [Y/N]: ";

    you may not see that question as it doesn't end in a newline and won't
    get flushed. set $| to make sure that works. see perlvar for info on $|.

    DO> if (my $decision = <STDIN> !~ /^[yY]/) {

    unless (my $decision = <STDIN> =~ /^y/i ) {

    use unless and rarely use !~. it is clearer. and the /i modifier
    eliminates the need for the char class


    DO> # Open the files.

    DO> open ( INFILE, "<$infile" ) or
    DO> die "Unable to open $infile.\n$!";

    DO> open ( OUTFILE, ">$outfile" ) or
    DO> die "Unable to open $outfile.\n$!";


    DO> # Start the counter, and process the files.

    DO> my $count = 0;
    DO> while ( <INFILE> ) {
    DO> # If the remove_numbers flag isn't set,
    DO> # increment the counter, prepend number.
    DO> unless ( $remove_numbers ) {
    DO> $count++;
    DO> $_ = "$count: ".$_;
    DO> } else {
    DO> # Otherwise strip number prefixes.
    DO> $_ =~ s/^\d+://;

    again, no need for $_ there.

    DO> }
    DO> print OUTFILE $_;

    same is true here. print defaults to $_.

    DO> }

    overall it is ok. some minor style issues and nothing very buggy at
    first glance. but then it doesn't do much. :)

    uri

    --
    Uri Guttman ------ [email]uri@stemsystems.com[/email] -------- [url]http://www.stemsystems.com[/url]
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- [url]http://jobs.perl.org[/url]
    Uri Guttman Guest

  4. #3

    Default Re: Seeking critique of simple file line numbering code.

    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    On Fri, 15 Aug 2003 15:14:08 -0700, David Oswald wrote:
    > I realize that grep performs some of this same functionality, but I just
    > wanted to create the tool on my own for the experience. To that end, I'm
    > also interested in hearing how I might clean it up from every standpoint
    > (style, robustness, etc.). This script reads infile, prepends a line number
    > to each line in the file, and outputs it as outfile. Come to think of it, I
    > probably should have just written the output to stdout to make it easier to
    > redirect from the shell. But this is just for discussion's sake.
    >
    > It's pretty basic, and the comments within the file should tell what's going
    > on.
    Its pretty good. Instead of $count, you can use $. (its the line number).

    Programs like this also become much simpler when ran using stdin and
    stdout:
    perl -wpe 's/^/$.: /' < infile > outfile
    perl -wpe 's/^$.: //' < infile > outfile

    or even:
    #!/usr/bin/perl -wp
    BEGIN {
    use strict;
    use Getopt::Std;
    use vars qw/%opts/;
    getopts('s', \%opts);
    }
    $opts{s} ? s/^$.: // : s/^/$.: /
    __END__

    - Brian
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.2 (GNU/Linux)

    iD8DBQE/PWtdiK/rA3tCpFYRAhi0AJ4mF9vsdzs5XKkB+qmsGW11EoWgPwCeKV7R
    MoPjq18u5V7f/CyG0pRGMqI=
    =YW+B
    -----END PGP SIGNATURE-----

    Brian Harnish Guest

  5. #4

    Default Re: Seeking critique of simple file line numbering code.

    David Oswald wrote:
    >
    > I realize that grep performs some of this same functionality, but I just
    > wanted to create the tool on my own for the experience. To that end, I'm
    > also interested in hearing how I might clean it up from every standpoint
    > (style, robustness, etc.). This script reads infile, prepends a line number
    > to each line in the file, and outputs it as outfile. Come to think of it, I
    > probably should have just written the output to stdout to make it easier to
    > redirect from the shell. But this is just for discussion's sake.
    >
    > It's pretty basic, and the comments within the file should tell what's going
    > on.
    >
    > #!/usr/bin/perl
    >
    > # Usage:
    > # linenum [-s] infile [outfile]
    >
    > # linenum writes outfile with line numbers prepended
    > # to each line in infile.
    >
    > # The -s flag causes line numbers in the format of /^d+:/
    > # to be stripped. Use -s to un-do what was done
    > # by linenum.
    >
    > use strict;
    > use warnings;
    >
    > # Strip and save command line switches.
    >
    > my @switch;
    > foreach ( @ARGV ) {
    > if ( $_ =~ /^-(.)/ ) {
    > push @switch, $1;
    > shift @ARGV;
    > }
    > }
    >
    > # Check for -s switch.
    >
    > my $remove_numbers = 0;
    > foreach ( @switch ) {
    > if ( $_ eq "s" ) {
    > $remove_numbers = 1;
    > } else {
    > print "Invalid option, -$_.\n";
    > print "Usage: linenum.pl [-s] infile [outfile]\n";
    > exit;
    > }
    > }
    >
    > # Pull in the filenames.
    >
    > my ( $infile, $outfile ) = @ARGV;
    >
    > # If outfile wasn't specified, make up a name.
    >
    > $outfile = $outfile || $infile.".out";
    >
    > # Test for file existances.
    >
    > unless ( -e $infile ) {
    > print "$infile doesn't exist.\n";
    > print "Exiting.\n";
    > exit;
    > }
    >
    > if ( -e $outfile ) {
    > print "$outfile already exists\n";
    > print "Overwrite? [Y/N]: ";
    > if (my $decision = <STDIN> !~ /^[yY]/) {
    > print "Aborting.\n";
    > exit;
    > }
    > }
    >
    > # Open the files.
    >
    > open ( INFILE, "<$infile" ) or
    > die "Unable to open $infile.\n$!";
    >
    > open ( OUTFILE, ">$outfile" ) or
    > die "Unable to open $outfile.\n$!";
    >
    > # Start the counter, and process the files.
    >
    > my $count = 0;
    > while ( <INFILE> ) {
    > # If the remove_numbers flag isn't set,
    > # increment the counter, prepend number.
    > unless ( $remove_numbers ) {
    > $count++;
    > $_ = "$count: ".$_;
    > } else {
    > # Otherwise strip number prefixes.
    > $_ =~ s/^\d+://;
    > }
    > print OUTFILE $_;
    > }
    >
    > # Sweep up, turn out the lights, lock the
    > # door on the way out.
    > close ( INFILE ) or
    > die "Unable to close $infile.\n$!";
    >
    > close ( OUTFILE ) or
    > die "Unable to close $outfile.\n$!";

    From another thread, I've recently learned that $.
    (dollar dot) contains the line number from your
    input file. You don't have to keep your own
    $count variable.

    (Lots of good learnin' in this group. :)
    Mike
    Michael P. Broida Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139