-4

I need to write a perl program that accept command lines arguments which can be concatenated e.g.

myPerl.pl -l -c -d    same as    myPerl.pl  -lcd

The only constrains is that I couldn't use build in modules such as "Getopts", anyone know of anything else I could do to realize this easily.

tshepang
  • 12,111
  • 21
  • 91
  • 136
user685275
  • 2,097
  • 8
  • 26
  • 32
  • 8
    Why can't you use modules? They were built to solve these problems, so why re-invent the wheel? – Andy White Apr 29 '11 at 21:38
  • 5
    Unless this is a homework assignment, you should be using [Getopt::Long](http://search.cpan.org/perldoc?Getopt::Long) or a similar module. Getopt::Long is part of the core Perl distribution, so it's pretty much guaranteed to be available. – cjm Apr 29 '11 at 21:49

4 Answers4

10

Look at Getopt::Long under Bundling.

Update: Oh, without modules. This is homework. Well, copy the code out of Getopt::Long then.

runrig
  • 6,486
  • 2
  • 27
  • 44
5

No modules? Really? That's like so perl4. :)

Ok then, so here’s how we always did it in perl4:

ARG: while (@ARGV && $ARGV[0] =~ s/^-(?=.)//) {
OPT:    for (shift @ARGV) {

            m/^$/        && do {                                 next ARG; };
            m/^-$/       && do {                                 last ARG; };

            s/^0//       && do { $nullpaths++;                   redo OPT; };
            s/^f//       && do { $force++;                       redo OPT; };
            s/^l//       && do { $reslinking++;                  redo OPT; };
            s/^I//       && do { $inspect++;                     redo OPT; };
            s/^i//       && do { $careful++;                     redo OPT; };
            s/^v//       && do { $verbose++;                     redo OPT; };
            s/^V//       && do { $verbose += 2;                  redo OPT; };  # like two -v's
            s/^m//       && do { $renaming++;                    redo OPT; };
            s/^n//       && do { $nonono++;                      redo OPT; };
            s/^N//       && do { $nonono += 2;                   redo OPT; };  # like two -n's
            s/^q//       && do { $quiet++;                       redo OPT; };

            s/^F(.*)//s  && do { push @flist, $1 || shift @ARGV; redo OPT; };

            &usage("Unknown option: $_");
        }
    }

Isn’t that swell? :)

That same approach still works today, but it might get you talked about.

tchrist
  • 78,834
  • 30
  • 123
  • 180
2

It is not easy to parse arguments reliably, which is why there are a myriad modules in the Getopts::* list (where, in this context, myriad ≈ 180). There are lots of possible conventions to deal with. In the example command line you show, should the last argument (-lcd) be treated as an option or as a file like the 'same', 'as', 'myPerl.pl' arguments probably are? Is the 'same' an argument to the -d option, or a separate 'file name' option? Can single-letter options be grouped? Can arguments be attached to options? Must they be attached? Must they be separate? Do you have multi-letter options or only single-letter options?

Until you have defined issues such as these - and how '-' and '--' are handled - you can't begin to do a decent job writing your code.

You may find answers to these questions of use:

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

I agree, you should use modules. Anyway, here's one attempt you can build upon:

use strict;
use warnings;
my @opts = grep /^-\w+/, @ARGV;
print "(1) @opts\n" if @opts;
my @normalized = sort grep /\w/, map { split /(-|)/ } @opts;
print "(2) @normalized\n" if @normalized;
Lumi
  • 14,775
  • 8
  • 59
  • 92
  • This is so cool. Is it OK if you could just explain a bit about your `@normalized` part, a bit deep for a beginner like me. But anyways, thanks a lot, this is great. – user685275 Apr 29 '11 at 22:16
  • Well, `@normalized` is a pipeline of processing steps. Read from right to left. First, `@opts` can have stuff like `-x` or like `-yyy`. We want to normalize everything to `x` or `y`, because then we can treat it uniformly. We use `split` to split on either `-` or the empty string. The return value of this `split` is a list of single letters or empty strings. We use `map` to apply this operation to each element. We use `grep` to filter out the empty strings. Then we `sort` it, just for tidiness. And then we call it `@normalized`. - Still, consider using a standard module for this kind of thing. – Lumi Apr 30 '11 at 08:55