Question

J'ai un script Perl qui définit des variables vers le haut pour les répertoires et les fichiers qu'il utilisera. Il exige également quelques variables à définir comme arguments de ligne de commande. Exemple:

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

Cela fonctionne très bien dans mes dev, test et environnements de production. Cependant, je tentais de le rendre plus facile à remplacer certaines variables (sans entrer dans le débogueur) pour le développement et les tests. (Par exemple, si je veux mettre mon fichier_entrée = « /tmp/my_input_file.dat »). Ma pensée était d'utiliser la fonction GetOptions pour gérer cela, quelque chose comme ceci:

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 ne peut être appelé une fois (pour autant que je sache). Les 4 premiers arguments dans mon premier snippit sont nécessaires, les 7 dernières directement au-dessus sont facultatifs. Je pense qu'une situation idéale serait d'installer les paramètres par défaut comme dans mon premier code snippit, et en quelque sorte remplacer tous ceux qui ont été fixés si les arguments ont été passés à la ligne de commande. Je pensais à stocker toutes mes options dans un hachage, puis en utilisant ce hachage lors de la configuration de chaque variable avec la valeur par défaut, sauf si une entrée existe dans le hachage, mais qui semble ajouter beaucoup de logique supplémentaire. Est-il possible d'appeler GetOptions en deux endroits différents dans le script?

Je ne sais pas si cela a du sens.

Merci!

Était-ce utile?

La solution

Voici une autre approche. Il utilise des tableaux de noms et un hachage pour stocker les options. Il fait toutes les options vraiment en option, mais valide celles nécessaires à moins d'inclure « --debug » sur la ligne de commande. Peu importe si vous utilisez « --debug », vous pouvez remplacer tous les autres.

Vous pouvez faire plus explicites contrôles logiques si ce qui est important, bien sûr. J'inclus « --debug » comme un exemple de la façon d'omettre les options de base comme « mount_point » si vous allez juste pour remplacer le « fichier_entrée » et « OUTPUT_FILE » variables de toute façon.

L'idée principale est ici que, en gardant des ensembles de noms d'options dans les tableaux, vous pouvez inclure des contrôles logiques contre les groupes avec relativement peu de code.

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

Autres conseils

On dirait que vous avez besoin de changer votre programme d'utiliser des fichiers de configuration plutôt que la configuration codée en dur. J'ai consacré un chapitre entier de Mastering Perl à ce sujet. Vous ne voulez pas modifier le code source pour tester le programme.

Il y a beaucoup de modules Perl sur CPAN qui rendent les fichiers de configuration d'une fonction facile à ajouter. Choisissez celui qui fonctionne le mieux pour vos données d'entrée.

Une fois que vous obtenez un meilleur modèle de configuration en place, vous pouvez facilement définir des valeurs par défaut, prendre des valeurs à partir de plusieurs endroits (fichiers, ligne de commande, etc.), et de tester facilement le programme avec des valeurs différentes.

Je pense que ce que je ferais est réglé et al à input_directory « undef », puis les mettre dans les getopts, et puis après, test s'ils sont encore FNUD et si oui les affecter comme indiqué. Si vos utilisateurs sont assez sophistiqués sur le plan technique pour comprendre « si je donne un chemin relatif, il est par rapport à $mount_point/$sub_dir », alors je ferais l'analyse syntaxique supplémentaire à la recherche d'un premier « /".

GetOptions peuvent être appelées avec un tableau comme ses données d'entrée. Lire le documentation .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top