2010-11-23 4 views
2

Ich habe ein Shell-Skript, das eine Linie spuckt wie folgt:Wie verwende ich Getopt :: Long, um Argumente zu parsen, die Leerzeichen enthalten können?

prog_name -options ... 

genauer zu sein, als Beispiel:

prog_name -filter_arg +define BOOST +noconvtest +actuate-long -disp_arg +define size=40 res=30

Bitte beachten Sie, dass es keine Anführungszeichen oben und ich habe keine Kontrolle, um das Shell-Skript zu modifizieren. [Ich bin mir jedoch nicht sicher, ob ich über ein anderes Programm Zitate in die obige Syntax einfügen kann.].

Jetzt möchte ich die oben auf ein Perl-Programm senden und die Möglichkeiten zu analysieren, so dass es +define BOOST +noconvtest +actuate-long der Option -filter_arg und +define size=40 res=30 der Option -disp_arg zuordnet.

Kann mir bitte jemand helfen?

Antwort

0

Ich bin nicht 100% sicher, aber ich denke nicht, dass Sie GetOpt :: Long verwenden können, zumindest nicht direkt.

Sie bräuchten Ich denke, eine erste selbst zu tun passieren, so etwas wie

my @filters; 
my $filter = []; 

foreach (@ARGV) { 
    if ($_ eq '+filter') { 
    push @filters, $filter; 
    $filter = []; 
    } else { 
    push @$filter, $_; 
    } 
} 
push @filters, $filter if @$filter; 

foreach (@filters) { 
    Getopt::Long::GetOptionsFromArray(@$_, ... 

    ... 
} 
+0

Vielen Dank Axeman, David und Colin. Schätzen Sie Ihre schnelle Antwort. Und im wahren Geist von Perl haben Sie gezeigt, wie das Problem auf verschiedene Arten gelöst werden kann! Ich habe viel gelernt, nachdem ich jeden Ihrer Beiträge sorgfältig gelesen habe. Herzliche Grüße. – Silver2010

+0

Verfehlt den Punkt, dass die Optionen von der Shell getrennt wurden, nicht von Perl. – Demi

2

Sie können einen Rückruf passieren wie so:

use strict; 
use warnings; 
use Getopt::Long; 

my $options = {}; 
@ARGV=qw<-filter_arg +define BOOST +noconvtest +actuate-long -disp_arg +define size=40 res=30>; 
GetOptions( 
    $options # store in hash ref 
    , qw<filter_arg define=s noconvtest actuate-long> 
    , disp_arg => sub { 
     # this will contain "+define size=40 res=30" 
     $options->{disp_arg} = join(' ', delete @ARGV[0..$#ARGV]); 
     } 
    ); 
5

Getopt::Long einfach die @ARGV Liste Parsen als vorgesehen zum Perl-Programm. Wenn die Parameter separate Einträge in der Liste @ARGV sind, werden sie von Getopt::Long auf diese Weise analysiert. Ihr Problem besteht darin, dass die Shell jedes Argument als separaten Parameter verwendet, da es keine Anführungszeichen gibt.

Ihre Wahl ist entweder, um die Parameter munge vor Ihrem Perl-Skript ausgeführt wird, oder durch munging @ARGV sich die Parameter in die Werte zu kombinieren, sie annehmen, sind in sein.

Für die erste Option können Sie verwenden sed nehmen Sie die Ausgabe Ihres Programms und fügen Sie die fehlenden Anführungszeichen hinzu. Wenn Sie Programm sind spuckt immer heraus Felder wie folgt aus:

prog_name -filter_arg +define BOOST +noconvtest +actuate-long -disp_arg +define size=40 res=30 

Sie könnten Rohr, das durch sed wie folgt aus:

$ orig_prog | sed -e 's/filter_arg /filter_arg "/' -e 's/ -disp_arg /" -disp_arg "/' -e 's/$/"/' 

Oder diese:

$ orig_prog | sed -e 's/^\(.*\) -filter_arg \(.*\) -disp_arg \(.*\)$/\1 -filter_arg "\2" -disp_arg "\3"/' 

Das wird die Anführungszeichen um Ihre Parameter und es wird so aussehen:

prog_name -filter_arg "+define BOOST +noconvtest +actuate-long" -disp_arg "+define size=40 res=30" 

Auf diese Weise wird @ARGV korrekt eingerichtet werden, so dass die GetOptions Funktion funktioniert so, wie Sie es wollen.

Der andere Weg ist @ARGV munge, wenn Sie Perl-Programm sind ausgeführt wird, bevor Sie rufen GetOptions:

my $value; 
my @newArgv; 
foreach my $param (@ARGV) { 
    if ($param =~ /^-/) { 
    if ($value) { 
    push (@newArgv, $value); 
    $value = ""; 
    } 
    push(@newArgv, $param); 
    } else { 
    $value = $value ? "$value $param" : "$param"; 
    } 
} 
push (@newArgv, $value) if ($value); 
@ARGV = @newArgv; 

In dem obigen Beispiel @ARGV die folgenden Werte haben:

@ARGV[0] = -filter_arg 
@ARGV[1] = +define BOOST +noconvtest +actuate-long 
@ARGV[2] = -disp_arg 
@ARGV[3] = +define size=40 res=30 

Und , Getopts::Long sollte nun so funktionieren, wie Sie es möchten. Eine kleine Randnotiz: In neueren Versionen von Getopt::Long können Sie neben @ARGV andere Arrays verwenden. Sie legen einfach das Array Sie als erstes Argument verwenden möchten in GetOptions:

use Getopt::Long qw(GetOptionsFromArray); 

GetOptionsFromArray (
    \@newArgs, 
    "filter_arg=s" => \$filter_arg, 
    "disp_arg=s" => \$disp_arg, 
); 
0

Getopt :: Long kann der Befehlszeile analysieren wie:

my (@filter_arg, @display_arg); 
GetOptions('filter_arg=f{1,5}' => \@filter_arg, 'display_arg=i{1,5}' => \@display_arg); 

Sie werden Arrays von parms bekommen.

Eine ausführlichere Erläuterung der bereits verfügbaren mehrwertigen Parameterbehandlung finden Sie unter Getopt::Long - Options with multiple values.