كيف يمكنني تجاوز التكوين الثابت تلوينها في برنامج بيرل بلدي؟

StackOverflow https://stackoverflow.com/questions/356337

  •  21-08-2019
  •  | 
  •  

سؤال

ولدي مخطوطة برل أن يضع المتغيرات بالقرب من أعلى الدلائل والملفات التي سوف تستخدم. كما يتطلب وجود عدد قليل من المتغيرات لتكون على النحو سائط سطر الأوامر. مثال:

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

وهذا يعمل بشكل جيد في بيئات ديف واختبار وإنتاج بلدي. ومع ذلك، كنت أحاول أن يجعل من الاسهل لتجاوز المتغيرات معينة (دون الخوض في مصحح) لتطوير واختبار. (على سبيل المثال، إذا كنت ترغب في تعيين بلدي input_file = "/tmp/my_input_file.dat"). كان تفكيري في استخدام وظيفة GetOptions للتعامل مع هذا، شيء من هذا القبيل:

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 مرة واحدة (بقدر ما أعرف). يطلب من الحجج 4 الأولى في أول SNIPPIT بلدي، وآخر 7 اختيارية فوق مباشرة. وأعتقد أن الوضع المثالي هو أن يكون لإعداد التخلف كما هو الحال في بلدي أولا SNIPPIT الرمز، ومن ثم تجاوز بطريقة أو بأخرى أي منها التي تم وضعها إذا تم تمرير الحجج في سطر الأوامر. فكرت في تخزين كل ما عندي من الخيارات في تجزئة ومن ثم استخدام تلك البعثرة عند إعداد كل متغير مع القيمة الافتراضية ما لم يوجد إدخال في التجزئة، ولكن يبدو أن تضيف الكثير من منطق إضافية. هل هناك طريقة للاتصال GetOptions في مكانين مختلفين في النص؟

وإذا لم تكن متأكدا أن يجعل من أي معنى.

وشكرا!

هل كانت مفيدة؟

المحلول

وهنا بأسلوب مختلف. ويستخدم صفائف أسماء وتجزئة لتخزين الخيارات. يجعل كل الخيارات اختياري حقا، ولكن بالتحقق من صحة تلك المطلوبة إلا إذا قمت بتضمين "--debug" على سطر الأوامر. بغض النظر عما إذا كنت تستخدم "--debug"، يمكنك تجاوز أي من الآخرين.

هل يمكن أن تفعل الشيكات المنطق أكثر وضوحا إذا كان هذا هو مهم بالنسبة لك، بالطبع. I شملت "--debug" كمثال على كيفية حذف الخيارات الأساسية مثل "mount_point" إذا كنت مجرد الذهاب لتجاوز "input_file" والمتغيرات "output_file" على أي حال.

والفكرة الرئيسية هنا هو أن طريق الحفاظ على مجموعات من أسماء الخيار في المصفوفات، يمكنك تضمين الشيكات المنطق ضد الجماعات مع رمز صغيرة نسبيا.

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

نصائح أخرى

وهذا يبدو وكأنه كنت بحاجة إلى تغيير البرنامج لاستخدام ملفات التكوين بدلا من تكوين الثابت تلوينها. وكرست فصلا كاملا من اتقان بيرل على ذلك. كنت لا تريد تغيير شفرة المصدر لاختبار البرنامج.

وهناك العديد من وحدات بيرل على CPAN التي تجعل تكوين ملفات ميزة سهلة لإضافة. اختيار واحد أن يعمل على نحو أفضل لإدخال البيانات الخاصة بك.

وبمجرد الحصول على نموذج التكوين أفضل في مكان، يمكنك بسهولة تعيين القيم الافتراضية، واتخاذ القيم من أماكن متعددة (ملفات، سطر الأوامر، الخ)، وسهولة اختبار البرنامج مع قيم مختلفة.

وأعتقد أن ما أود القيام به هو وضع input_directory آخرون إلى "نديف"، ومن ثم وضعها في getopts، ثم بعد ذلك، اختبار إذا ما كنت لا تزال نديف وإذا كان الأمر كذلك التنازل عنها كما هو مبين. إذا كان المستخدمون هم تطورا من الناحية التقنية ما يكفي لفهم "إذا أعطي مسار نسبي انها نسبة إلى $mount_point/$sub_dir"، ثم كنت تفعل تحليل إضافي تبحث عن الأولي "/".

يمكن أن يسمى

وGetOptions مع مجموعة وإدخال البيانات بها. قراءة الوثائق .

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top