getopt, getopts বা ম্যানুয়াল পার্সিং - আমি যখন সংক্ষিপ্ত এবং দীর্ঘ উভয় বিকল্পকে সমর্থন করতে চাই তখন কী ব্যবহার করব?


32

বর্তমানে আমি বাশ স্ক্রিপ্ট লিখছি যার নিম্নলিখিত প্রয়োজনীয়তা রয়েছে:

  • এটি ইউনিক্স / লিনাক্স প্ল্যাটফর্মের বিভিন্ন ধরণের চলতে হবে
  • এটি সংক্ষিপ্ত এবং (জিএনইউ) দীর্ঘ উভয় বিকল্পকেই সমর্থন করে

আমি জানি যে getoptsবহনযোগ্যতার ক্ষেত্রে এটি পছন্দসই উপায় তবে এএফআইএইকি এটি দীর্ঘ বিকল্পগুলি সমর্থন করে না।

getoptদীর্ঘ বিকল্পগুলি সমর্থন করে তবে বাশগুইড এর বিরুদ্ধে দৃ strongly ়তার সাথে প্রস্তাব দেয়:

কখনই গোটপট (1) ব্যবহার করবেন না। getopt খালি আর্গুমেন্টের স্ট্রিং বা এম্বেড শ্বেতস্পেসের সাথে যুক্তিগুলি পরিচালনা করতে পারে না। দয়া করে ভুলে যাবেন যে এটি কখনও ছিল।

সুতরাং, ম্যানুয়াল বিশ্লেষণের বিকল্পটি এখনও রয়েছে। এটি ত্রুটি-প্রবণ, বেশ কয়েকটি বয়লারপ্লিট কোড উত্পন্ন করে এবং আমার নিজের দ্বারা ত্রুটিগুলি পরিচালনা করতে হবে (আমি মনে getopt(s)করি নিজেরাই ত্রুটি-পরিচালনা পরিচালনা করি )।

সুতরাং, এই ক্ষেত্রে পছন্দসই পছন্দ কি হবে?


উত্তর:


9

এটি যদি ইউনিসির একটি ব্যাপ্তির কাছে বহনযোগ্য হতে হয় তবে আপনাকে পসিক্স sh এ আটকে থাকতে হবে। এবং এএফএআইইউতে আপনার কাছে কেবল হাতে হাত দিয়ে যুক্তি রোলিংয়ের বিকল্প নেই।


25

getoptবনাম getoptsএকটি ধর্মীয় বিষয় বলে মনে হচ্ছে। বিরুদ্ধে আর্গুমেন্ট হিসাবে getoptমধ্যে ব্যাশ প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী :

  • " getoptখালি আর্গুমেন্ট স্ট্রিং হ্যান্ডেল করতে পারে না" দিয়ে একটি পরিচিত সমস্যা পড়ুন বলে মনে হয় ঐচ্ছিক আর্গুমেন্ট, যা এটি দেখে মনে হচ্ছে getopts(অন্তত পড়া থেকে এ সব সমর্থন করে না help getoptsব্যাশ 4.2.24 জন্য)। থেকে man getopt:

    getopt (3) একটি খালি alচ্ছিক আর্গুমেন্ট প্রদত্ত alচ্ছিক আর্গুমেন্টগুলির সাথে দীর্ঘ বিকল্পগুলি পার্স করতে পারে (তবে সংক্ষিপ্ত বিকল্পগুলির জন্য এটি করতে পারে না)। এই getopt (1) alচ্ছিক আর্গুমেন্টগুলি এমন আচরণ করে যা খালি থাকে যেন তারা উপস্থিত না থাকে।

আমি জানি না যে " getoptএম্বেড শ্বেতস্পেসের সাথে যুক্তিগুলি [...] পরিচালনা করতে পারে না" কোথা থেকে এসেছে তবে আসুন এটি পরীক্ষা করে দেখুন:

  • test.sh:

    #!/usr/bin/env bash
    set -o errexit -o noclobber -o nounset -o pipefail
    params="$(getopt -o ab:c -l alpha,bravo:,charlie --name "$0" -- "$@")"
    eval set -- "$params"
    
    while true
    do
        case "$1" in
            -a|--alpha)
                echo alpha
                shift
                ;;
            -b|--bravo)
                echo "bravo=$2"
                shift 2
                ;;
            -c|--charlie)
                echo charlie
                shift
                ;;
            --)
                shift
                break
                ;;
            *)
                echo "Not implemented: $1" >&2
                exit 1
                ;;
        esac
    done
    
  • সঞ্চালন করুন:

    $ ./test.sh -
    $ ./test.sh -acb '   whitespace   FTW   '
    alpha
    charlie
    bravo=   whitespace   FTW   
    $ ./test.sh -ab '' -c
    alpha
    bravo=
    charlie
    $ ./test.sh --alpha --bravo '   whitespace   FTW   ' --charlie
    alpha
    bravo=   whitespace   FTW   
    charlie
    

আমার কাছে চেক এবং সাথীর মতো মনে হচ্ছে তবে আমি নিশ্চিত যে কেউ কীভাবে বাক্যটিকে পুরোপুরি ভুল বুঝে তা দেখিয়ে দেবে। অবশ্যই বহনযোগ্যতা ইস্যু এখনও দাঁড়িয়ে; কোনও পুরানো বা কোনও বাশ পাওয়া যায় না এমন প্ল্যাটফর্মগুলিতে বিনিয়োগের জন্য সময় কতটা তা আপনাকে সিদ্ধান্ত নিতে হবে। আমার নিজস্ব টিপটি হ'ল ইয়াজিএনআই এবং কেআইএসএস নির্দেশিকা - কেবলমাত্র সেই নির্দিষ্ট প্ল্যাটফর্মগুলির জন্য বিকাশ করা হবে যা আপনি জানেন যে ব্যবহার করা যাচ্ছে। শেল কোড বহনযোগ্যতা সাধারণত 100% যায় কারণ বিকাশের সময় অসীমের দিকে যায়।


11
ওপি অনেকগুলি ইউনিক্স প্ল্যাটফর্মের জন্য পোর্টেবল হওয়ার প্রয়োজনীয়তার কথা উল্লেখ করেছে যখন getoptআপনি এখানে লিনাক্স-নির্দিষ্ট করেছেন। মনে রাখবেন যে getoptএটি কোনও অংশ নয় bash, এটি একটি জিএনইউ ইউটিলিটিও নয় এবং লিনাক্সে ইউট-লিনাক্স প্যাকেজটি সরবরাহ করা হয়।
স্টাফেন চেজেলাস

2
বেশিরভাগ প্ল্যাটফর্মে রয়েছে getopt, কেবল লিনাক্স এএফএইকি এমন একটি উপস্থিত থাকে যা দীর্ঘতর বিকল্প বা আর্গুমেন্টে ফাঁকা সমর্থন করে। অন্যগুলি কেবলমাত্র সিস্টেম ভি সিন্টেক্স সমর্থন করে।
স্টাফেন চেজেলাস

7
getoptলিনাক্স প্রকাশের অনেক আগে সিস্টেম ভি থেকে আসা aতিহ্যবাহী কমান্ড। getoptকখনও মানসম্মত ছিল না। পসিক্স, ইউনিক্স বা লিনাক্সের (এলএসবি) কোনওটিই getoptকমান্ডটি মানক করে না । getoptsতিনটিতে নির্দিষ্ট করা হয়েছে তবে দীর্ঘ বিকল্পগুলির জন্য সমর্থন ছাড়াই।
স্টাফেন চেজেলাস

1
কেবল এই আলোচনায় যুক্ত করার জন্য: এটি প্রচলিত নয় getopt। এটি @ স্টাফেনচেজেলাস দ্বারা উল্লিখিত লিনাক্স-ইউজ গন্ধ। এটিতে লিগ্যাসি অপশন রয়েছে যা উপরে বর্ণিত সিনট্যাক্সটি অক্ষম করবে, বিশেষত ম্যানপেজটি "GETOPT_COMPATIBLE SYNOPSIS তে বর্ণিত হিসাবে প্রথম কলিং ফর্ম্যাটটি ব্যবহার করার জন্য জোর করে" states তবে আপনি যদি আশা করতে পারেন যে টার্গেট সিস্টেমগুলি এই প্যাকেজটি ইনস্টল করা হয়েছে তবে এটি পুরোপুরি
চলার

1
ওপির লিঙ্কটি দাবি করে যে "গোটপটের প্রচলিত সংস্করণগুলি শূন্যস্থান যুক্ত ফাঁকা যুক্তিযুক্ত স্ট্রিং, বা যুক্তিগুলি পরিচালনা করতে পারে না।" এবং যে গিওপেটের ইউজ-লিনাক্স সংস্করণ ব্যবহার করা উচিত নয় তার কোনও প্রমাণ নেই এবং এটি আর সঠিক নয়। একটি দ্রুত সমীক্ষা (5+ বছর পরে) দেখায় যে আর্কলিনাক্স, এসইউএসই, উবুন্টু, রেডহ্যাট, ফেডোরা, এবং সেন্টোস (সেইসাথে সর্বাধিক ডেরাইভেটিভ ভেরিয়েন্টস) থেকে পাওয়া গেওপ্টের ডিফল্ট সংস্করণ হোয়াইটস্পেসের সাথে সমস্ত সমর্থন .চ্ছিক আর্গুমেন্ট এবং যুক্তিগুলি সমর্থন করে।
mtalexan

10

এখানে পসিক্স শেল ফাংশন হিসাবে লেখা এই গিওপটস_লং রয়েছে যা আপনি আপনার স্ক্রিপ্টের অভ্যন্তরে এম্বেড করতে পারেন।

নোট করুন যে লিনাক্স getopt(থেকে util-linux) traditional তিহ্যগত মোডে না থাকলে সঠিকভাবে কাজ করে এবং দীর্ঘ বিকল্পগুলি সমর্থন করে, তবে আপনার যদি অন্য ইউনিয়নে পোর্টেবল হওয়ার দরকার হয় তবে আপনার পক্ষে সম্ভবত এটি বিকল্প নয়।

Ksh93 ( getopts) এবং zsh ( zparseopts) এর সাম্প্রতিক সংস্করণগুলিতে দীর্ঘ বিকল্পগুলি পার্সিংয়ের জন্য অন্তর্নির্মিত সমর্থন রয়েছে যা বেশিরভাগ ইউনিসের জন্য উপলব্ধ (যদিও এটি প্রায়শই ডিফল্টরূপে ইনস্টল করা হয় না) আপনার পক্ষে বিকল্প হতে পারে।

অন্য বিকল্পটি ব্যবহার করা হবে perlএবং এর Getopt::Longমডিউল উভয়ই আজকাল বেশিরভাগ ইউনিসিতে পাওয়া উচিত, পুরো স্ক্রিপ্টটি লিখে perlবা কেবল পার্লকে কল করে কেবল বিকল্পটি বিশ্লেষণ করতে এবং শেলকে নিষ্ক্রিয় তথ্য ফিড করতে হবে। কিছুটা এইরকম:

parsed_ops=$(
  perl -MGetopt::Long -le '

    @options = (
      "foo=s", "bar", "neg!"
    );

    Getopt::Long::Configure "bundling";
    $q="'\''";
    GetOptions(@options) or exit 1;
    for (map /(\w+)/, @options) {
      eval "\$o=\$opt_$_";
      $o =~ s/$q/$q\\$q$q/g;
      print "opt_$_=$q$o$q"
    }' -- "$@"
) || exit
eval "$parsed_ops"
# and then use $opt_foo, $opt_bar...

দেখুন perldoc Getopt::Longএটা করতে পারেন কি জন্য এবং কিভাবে এটা অন্য বিকল্প পারজার থেকে পৃথক।


2

এই বিষয়ে প্রতিটি আলোচনা ম্যানুয়ালি পার্সিং কোড লেখার বিকল্পটি হাইলাইট করে - তবেই আপনি কার্যকারিতা এবং বহনযোগ্যতা সম্পর্কে নিশ্চিত হতে পারবেন। আমি আপনাকে এমন কোড না লিখতে পরামর্শ দিচ্ছি যা আপনি সহজে ব্যবহারযোগ্য ওপেন সোর্স কোড জেনারেটর দ্বারা তৈরি এবং পুনঃ জেনারেট করতে পারেন। আরগবাশ ব্যবহার করুন , যা আপনার সমস্যার সুনির্দিষ্ট উত্তর দেওয়ার জন্য ডিজাইন করা হয়েছে। এটা একটা হয় ভাল নথিভুক্ত কোড একটি হিসাবে উপলব্ধ জেনারেটরের কম্যান্ড-লাইন আবেদন , অনলাইন বা যেমন Docker ইমেজ

আমি বাশ লাইব্রেরিগুলির বিরুদ্ধে পরামর্শ দিচ্ছি, তাদের মধ্যে কিছু ব্যবহার করে getopt(যা বেশিরভাগ অপ্রয়োজনীয় করে তোলে) এবং এটি আপনার স্ক্রিপ্টের সাহায্যে বিশাল আকারের অপঠনযোগ্য শেল ব্লাবকে বান্ডিল করা একটি ব্যথা।


0

আপনি getoptএটি সমর্থন করে এমন সিস্টেমে ব্যবহার করতে পারেন এবং যে সিস্টেমগুলি না করে তাদের পিছনে পড়ে ব্যবহার করতে পারেন।

উদাহরণস্বরূপ, pure-getoptজিএনইউর জন্য ড্রপ-ইন প্রতিস্থাপন হতে খাঁটি বাশে প্রয়োগ করা হয়েছে getopt

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.