Frage

Ich habe einen Perl-Skript, das für Verzeichnisse Variablen in der Nähe der Spitze aufstellt und Dateien, die sie verwenden werden. Es erfordert auch ein paar Variablen als Befehlszeilenargumente gesetzt werden. Beispiel:

use Getopt::Long;

my ($mount_point, $sub_dir, $database_name, $database_schema);
# Populate variables from the command line:
GetOptions(
    'mount_point=s'       => \$mount_point,
    'sub_dir=s'           => \$sub_dir,
    'database_name=s'     => \$database_name,
    'database_schema=s'   => \$database_schema
);
# ...  validation of required arguments here

################################################################################
# Directory variables
################################################################################
my $input_directory    = "/${mount_point}/${sub_dir}/input";
my $output_directory   = "/${mount_point}/${sub_dir}/output";
my $log_directory      = "/${mount_point}/${sub_dir}/log";
my $database_directory = "/db/${database_name}";
my $database_scripts   = "${database_directory}/scripts";

################################################################################
# File variables
################################################################################
my $input_file       = "${input_dir}/input_file.dat";
my $output_file      = "${output_dir}/output_file.dat";
# ... etc

Das funktioniert gut in meinen Entwickler, Test- und Produktionsumgebungen. Aber ich habe versucht, es einfacher zu machen, bestimmte Variablen außer Kraft zu setzen (ohne in den Debugger gehen) für die Entwicklung und Erprobung. (Zum Beispiel, wenn ich möchte, dass meine input_file = „/tmp/my_input_file.dat“ eingestellt). Mein Gedanke war, die GetOptions Funktion zu verwenden, um dies zu handhaben, so etwas wie folgt aus:

GetOptions(
    'input_directory=s'      => \$input_directory,
    'output_directory=s'     => \$output_directory,
    'database_directory=s'   => \$database_directory,
    'log_directory=s'        => \$log_directory,
    'database_scripts=s'     => \$database_scripts,
    'input_file=s'           => \$input_file,
    'output_file=s'          => \$output_file
);

GetOptions kann nur einmal aufgerufen werden (soweit ich weiß). Die ersten 4 Argumente in meinem ersten snippit erforderlich sind, die letzten 7 direkt über optional sind. Ich denke, eine ideale Situation die Standardwerte wie in meinem ersten Code snippit einrichten würde, und dann außer Kraft setzen irgendwie einer von ihnen, die gesetzt wurden, wenn Argumente in der Befehlszeile übergeben wurden. Ich dachte an alle meine Optionen in einem Hash zu speichern und dann diese Hash verwenden, wenn jede Variable mit dem Standardwert einrichten, es sei denn ein Eintrag in der Hash vorhanden ist, aber das scheint eine Menge zusätzlicher Logik hinzuzufügen. Gibt es eine Möglichkeit GetOptions an zwei verschiedenen Stellen im Skript zu nennen?

Nicht sicher, ob der Sinn macht.

Danke!

War es hilfreich?

Lösung

Hier ist ein weiterer Ansatz. Es verwendet Arrays von Namen und ein Hash-Optionen zu speichern. Es macht alle Optionen wirklich optional, aber überprüft die erforderlichen diejenigen, wenn Sie „debug“ in der Befehlszeile enthalten. Unabhängig davon, ob Sie „debug“, können Sie alle anderen außer Kraft setzen.

Sie können explizite Logik überprüft tun, wenn das für Sie, natürlich wichtig ist. I enthielt „debug“ als ein Beispiel dafür, wie die grundlegenden Optionen wie „mount_point“ weglassen, wenn Sie nur die „input_file“ und „output_file“ Variablen sowieso außer Kraft zu setzen.

Die Grundidee dabei ist, dass durch Sätze von Optionsnamen in Arrays zu halten, können Sie logische Kontrollen gegen die Gruppen mit relativ wenig Code enthalten.

use Getopt::Long;

my @required_opts = qw(
    mount_point
    sub_dir
    database_name
    database_schema
);

my @internal_opts = qw(
    input_directory
    output_directory
    log_directory
    database_directory
    database_scripts
    input_file
    output_file
);

my @opt_spec = ("debug", map { "$_:s" } @required_opts, @internal_opts);

# Populate variables from the command line:
GetOptions( \(my %opts), @opt_spec );

# check required options unless 
my @errors = grep { ! exists $opts{$_} } @required_options;
if ( @errors && ! $opts{debug} ) {
    die "$0: missing required option(s): @errors\n";
}

################################################################################
# Directory variables
###############################################################################
my $opts{input_directory}    ||= "/$opts{mount_point}/$opts{sub_dir}/input";
my $opts{output_directory}   ||= "/$opts{mount_point}/$opts{sub_dir}/output";
my $opts{log_directory}      ||= "/$opts{mount_point}/$opts{sub_dir}/log";
my $opts{database_directory} ||= "/db/$opts{database_name}";
my $opts{database_scripts}   ||= "$opts{database_directory}/scripts";

################################################################################
# File variables
################################################################################
my $opts{input_file}    ||= "$opts{input_directory}/input_file.dat";
my $opts{output_file}   ||= "$opts{output_directory}/output_file.dat";
# ... etc

Andere Tipps

Es klingt wie Sie Ihr Programm ändern müssen Konfigurationsdateien zu verwenden, anstatt hartcodierte Konfiguration. Ich widmete ein ganzes Kapitel von Mastering Perl diese . Sie wollen nicht Quellcode ändern, um das Programm zu testen.

Es gibt viele Perl-Module auf CPAN, die Konfiguration machen Dateien eine einfache Funktion hinzuzufügen. Wählen Sie das, das am besten für Ihre Eingangsdaten funktioniert.

Wenn Sie ein besseres Konfigurationsmodell in Platz zu bekommen, können Sie einfach Standardwert festgelegt, nehmen Werte von mehreren Stellen (Dateien, Befehlszeile, usw.), und testen Sie das Programm problemlos mit unterschiedlichen Werten.

Ich denke, was ich tun würde, wird input_directory et al auf „undefiniert“, und sie dann in den getopts setzen, und dann danach, Test, ob sie noch undefiniert sind und wenn sie so zuordnen, wie dargestellt. Wenn die Benutzer genug technisch anspruchsvolle verstehen „wenn ich einen relativen Pfad geben ist es in Bezug auf $mount_point/$sub_dir“, dann würde ich zusätzliches Parsing tut Suche nach einem anfänglichen „/".

GetOptions kann mit einem Array als seine Eingangsdaten aufgerufen werden. Lesen Sie die Dokumentation .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top