user1831897
user1831897

Reputation: 11

Perl - Parsing Arguments/Options with REGEX

I'm creating a perl script to convert a list of commands in a template file () and output them to another file in a different format in an output file ().

The commands in the template file will look as follows:

command1 --max-size=2M --type="some value"

I'm having some problems extracting the options and values from this string. So far i have:

m/(\s--\w*=)/ig

Which will return:

" --max-size="
" --type="

However I have no idea how to return both the option and value as a separate variable or how to accommodate for the use of quotes.

Could anyone steer me in the right direction?

side note: I'm aware that Getops does an awesome job at doing this from the command-line but unfortunately these commands are passed as strings :(

Upvotes: 0

Views: 843

Answers (3)

Axeman
Axeman

Reputation: 29854

Getopt::Std or Getopt::Long?

Have you looked at this option or this one?

Seems like there's no reason to reinvent the wheel.

Upvotes: 3

Ωmega
Ωmega

Reputation: 43673

use Data::Dumper;
$_ = 'command1 --max-size=2M a=ignore =ignore --switch --type="some value" --x= --z=1';
my %args;
while (/((?<=\s--)[a-z\d-]+)(?:="?|(?=\s))((?<![="])|(?<=")[^"]*(?=")|(?<==)(?!")\S*(?!"))"?(?=\s|$)/ig) {
  $args->{$1} = $2;
}
print Dumper($args);

---

$VAR1 = {
          'switch' => '',
          'x' => '',
          'type' => 'some value',
          'z' => '1',
          'max-size' => '2M'
        };

(test this demo here)

Upvotes: -1

ikegami
ikegami

Reputation: 385789

The code below produces

@args = ('command1', '--max-size=2M', '--type=some value');

That is suitable to pass to GetOptions as follows:

local @ARGV = @args;
GetOptions(...) or die;

Finally, the code:

for ($cmd) {
   my @args;
   while (1) {
      last if /\G \s* \z /xgc;

      /\G \s* /xgc;

      my $arg;
      while (1) {
         if (/\G ([^\\"'\s]) /xgc) {
            $arg .= $1;
         }
         elsif (/\G \\ /xgc) {
            /\G (.) /sxgc
               or die "Incomplete escape";

            $arg .= $1;
         }
         elsif (/\G (?=") /xgc) {
            /\G " ( (?:[^"\\]|\\.)* ) " /sxgc
               or die "Incomplete double-quoted arging";

            my $quoted = $1;
            $quoted =~ s/\\(.)/$1/sg;

            $arg .= $quoted;
         }
         elsif (/\G (?=') /xgc) {
            /\G ' ( [^']* ) ' /xgc
               or die "Incomplete single-quoted arging";

            $arg .= $1;
         }
         else {
            last;
         }
      }

      push @args, $arg;
   }

   @args
      or die "Blank command";

   ...
}

Upvotes: 0

Related Questions