অর্ডার না দেওয়া হলে আমি কীভাবে ব্যাশ স্ক্রিপ্টে alচ্ছিক যুক্তিগুলি পার্স করব?


13

নিম্নলিখিত প্রোগ্রামের জন্য ব্যাশ স্ক্রিপ্ট লেখার সময় আমি কীভাবে alচ্ছিক যুক্তি / পতাকাগুলি অন্তর্ভুক্ত করব তা নিয়ে আমি বিভ্রান্ত হয়ে পড়েছি:

প্রোগ্রামটির জন্য দুটি যুক্তি প্রয়োজন:

run_program --flag1 <value> --flag2 <value>

তবে, বেশ কয়েকটি alচ্ছিক পতাকা রয়েছে:

run_program --flag1 <value> --flag2 <value> --optflag1 <value> --optflag2 <value> --optflag3 <value> --optflag4 <value> --optflag5 <value> 

আমি বাশ স্ক্রিপ্টটি এমনভাবে চালাতে চাই যা এটির ব্যবহারকারীর যুক্তিগুলি গ্রহণ করে। যদি ব্যবহারকারীরা কেবলমাত্র দুটি যুক্তি ক্রমে ইনপুট করে থাকে তবে তা হবে:

#!/bin/sh

run_program --flag1 $1 --flag2 $2

তবে ifচ্ছিক যুক্তিগুলির কোনও যদি অন্তর্ভুক্ত থাকে তবে কী হবে? আমি মনে হবে এটা হবে

if [ --optflag1 "$3" ]; then
    run_program --flag1 $1 --flag2 $2 --optflag1 $3
fi

তবে যদি $ 4 দেওয়া হয় তবে $ 3 নয়?


getoptsআপনি কি চান তা ছাড়া, আপনি প্রতিটি পতাকা সনাক্ত করতে toচ্ছিক বা না সনাক্ত করতে একটি স্যুইচ স্টেটমেন্ট সহ একটি লুপ ব্যবহার করতে পারেন।
অরিয়ান


@ ওরিওন দিয়ে getopts, আমার প্রতিটি যুক্তির সংমিশ্রণটি নির্দিষ্ট করা দরকার? 3 এবং 4, 3 এবং 5, 3 এবং 4 এবং 5, ইত্যাদি?
শানজেংইয়াং

না, আপনি যদি সেগুলি পান তবে কেবল সেগুলি সেট করুন, অন্যথায় এটি এটি খুঁজে পাওয়া যায় নি বলে জানা গেছে, সুতরাং মূলত আপনি প্রতিটি বিকল্পটি "যেভাবেই হোক না কেন" কেবল "পেয়ে" যান এবং সেগুলিকে কোনও ক্রমে সুনির্দিষ্টভাবে উল্লেখ করুন if তবে কেবল বাশ ম্যান পৃষ্ঠাটি পড়ুন, এটি সব আছে।
অরিয়ান

@ ওরিওন আমি দুঃখিত, তবে আমি এখনও বেশ বুঝতে পারি না getopts। যাক আমি ব্যবহারকারীদের সমস্ত তর্ক দিয়ে স্ক্রিপ্টটি চালাতে বাধ্য করি: run_program.sh VAL VAL FALSE FALSE FALSE FALSE FALSEযা প্রোগ্রামটি চালায় program --flag1 VAL --flag2 VAL। আপনি যদি দৌড়েন run_program.sh VAL VAL FALSE 10 FALSE FALSE FALSE, প্রোগ্রাম হিসাবে চলতে হবে program --flag1 VAL --flag2 VAL --optflag2 10। আপনি কিভাবে এই ধরনের আচরণ পেতে পারেন getopts?
শানজেংইয়াং

উত্তর:


25

এই নিবন্ধটি দুটি ভিন্ন উপায় দেখায় - shiftএবং getopts(এবং দুটি পদ্ধতির সুবিধা এবং অসুবিধাগুলি নিয়ে আলোচনা করে)।

সঙ্গে shiftআপনার স্ক্রিপ্ট সৌন্দর্য $1, কি সিদ্ধান্ত নেয় ব্যবস্থা গ্রহণ করতে, এবং তারপর, executes shift, চলন্ত $2থেকে $1, $3থেকে $2, ইত্যাদি

উদাহরণ স্বরূপ:

while :; do
    case $1 in
        -a|--flag1) flag1="SET"            
        ;;
        -b|--flag2) flag2="SET"            
        ;;
        -c|--optflag1) optflag1="SET"            
        ;;
        -d|--optflag2) optflag2="SET"            
        ;;
        -e|--optflag3) optflag3="SET"            
        ;;
        *) break
    esac
    shift
done

আপনার সাথে অভিব্যক্তিটির getopts(সংক্ষিপ্ত) বিকল্পগুলি সংজ্ঞায়িত করুন while:

while getopts abcde opt; do
    case $opt in
        a) flag1="SET"
        ;;
        b) flag2="SET"
        ;;
        c) optflag1="SET"
        ;;
        d) optflag2="SET"
        ;;
        e) optflag3="SET"
        ;;
    esac
done

স্পষ্টতই, এগুলি কেবল কোড-স্নিপেটস এবং আমি বৈধতা রেখে গিয়েছি - পরীক্ষা করে যে বাধ্যতামূলক আরোগুলি পতাকা 1 এবং পতাকা 2 সেট করা আছে, ইত্যাদি checking

আপনি কোন পন্থাটি ব্যবহার করেন তা কিছুটা স্বাদের বিষয় - আপনি আপনার স্ক্রিপ্টটি কতটা পোর্টেবল করতে চান, আপনি কেবল সংক্ষিপ্ত (পসিক্স) বিকল্পের সাথে বাঁচতে পারেন বা আপনি দীর্ঘ (জিএনইউ) বিকল্পগুলি চান কিনা ইত্যাদি etc.


আমি সাধারণত এর while (( $# ))পরিবর্তে করি while :;এবং প্রায়শই *ক্ষেত্রে কোনও ত্রুটিটি দিয়ে চলে যাই
জেসেন

এটি শিরোনাম উত্তর দেয় কিন্তু প্রশ্ন নয়।
জেসেন

@ জেসেন আমি গত রাতে এই দিকে তাকিয়েছিলাম এবং কেন আমার জীবনের জন্য তা দেখতে পেলাম না। আজ সকালে এটি আরও পরিষ্কার (এবং আমি এখন ওরিওনের উত্তরও দেখেছি)। আমি আজ এই উত্তরটি পরে মুছে ফেলব (আমি প্রথমে আপনার মন্তব্যটি স্বীকার করতে চেয়েছিলাম, এবং এটি করার সহজ উপায় এটি বলে মনে হয়েছিল)।
জন এন

কোনও সমস্যা নেই, এটি এখনও একটি ভাল উত্তর, শুধু প্রশ্নটি এলোমেলো করে।
জেসেন

1
এনবি: set -o nounsetপ্রথম সমাধানের ক্ষেত্রে কোনও প্যারামিটার না দিলে ত্রুটি হয়ে যায়। স্থির করুন:case ${1:-} in
রাফেল

3

একটি অ্যারে ব্যবহার করুন।

#!/bin/bash

args=( --flag1 "$1" --flag2 "$2" )
[  "x$3" = xFALSE ] ||  args+=( --optflag1 "$3" )
[  "x$4" = xFALSE ] ||  args+=( --optflag2 "$4" )
[  "x$5" = xFALSE ] ||  args+=( --optflag3 "$5" )
[  "x$6" = xFALSE ] ||  args+=( --optflag4 "$6" )
[  "x$7" = xFALSE ] ||  args+=( --optflag5 "$7" )

program_name "${args[@]}"

এটি তাদের মধ্যে ফাঁকা স্থানগুলির সাথে সঠিকভাবে যুক্তিগুলি পরিচালনা করবে handle

আমি [সম্পাদনা] মোটামুটি একিভ্যালেন্ট সিনট্যাক্স ব্যবহার করছি args=( "${args[@]}" --optflag1 "$3" )তবে জি ম্যান আরও ভাল উপায়ের পরামর্শ দিয়েছিল।


1
আপনি এই বলে কিছুটা সামঞ্জস্য করতে পারেন args+=( --optflag1 "$3" )। আপনি আমাদের রেফারেন্স কাজের আমার উত্তর দেখতে চাইতে পারেন , ব্যাশ / পসিক্স শেলগুলিতে পরিবর্তনশীল উদ্ধৃতি দিতে ব্যর্থ হওয়ার সুরক্ষা সম্পর্কিত প্রভাব , যেখানে আমি এই কৌশলটি (শর্তসাপেক্ষে .চ্ছিক যুক্তি যুক্ত করে একটি অ্যারেতে একটি কমান্ড লাইন তৈরির) আলোচনা করি।
জি-ম্যান বলছেন 'মনিকাকে

@ জি-ম্যান ধন্যবাদ, আমি দেখতে পাইনি যে ডকুমেন্টেশনে বুঝতে পেরে [@]আমার সমস্যা সমাধানের জন্য পর্যাপ্ত সরঞ্জাম রয়েছে।
জেসেন

1

শেল স্ক্রিপ্টে, আর্গুমেন্টগুলি "$ 1", "$ 2", "$ 3" ইত্যাদি হয়। # আর্গুমেন্টের সংখ্যা। #।
যদি আপনার স্ক্রিপ্ট অপশনগুলি স্বীকৃতি না দেয় তবে আপনি বিকল্প সনাক্তকরণ ছেড়ে যেতে পারেন এবং সমস্ত আর্গুমেন্টকে অপারেশন হিসাবে বিবেচনা করতে পারেন।
বিকল্পগুলি সনাক্ত করতে গিওপটস বিল্টিন ব্যবহার করুন


0

যদি আপনার ইনপুট বিকল্পগুলি অবস্থানগত হয় (আপনি জানেন যে তারা কোথায় রয়েছে) এবং পতাকাগুলির সাথে নির্দিষ্ট না করা থাকে তবে আপনি যা চান তা কেবল কমান্ড লাইন তৈরি করা। তাদের সবার জন্য কমান্ড আর্গুমেন্টগুলি প্রস্তুত করুন:

FLAG1="--flag1 $1"
FLAG2="--flag2 $2"
OPTFLAG1=""
OPTFLAG2=""
OPTFLAG3=""
if [ xFALSE != x"$3" ]; then
   OPTFLAG1="--optflag1 $3"
fi
if [ xFALSE != x"$4" ]; then
   OPTFLAG2="--optflag2 $4"
fi
#the same for other flags

#now just run the program
runprogram $FLAG1 $FLAG2 $OPTFLAG1 $OPTFLAG2 $OPTFLAG3

যদি প্যারামিটারগুলি নির্দিষ্ট না করা থাকে, তবে কর্রসন্ডিং স্ট্রিং খালি থাকে এবং কিছুইতে প্রসারিত হয় না। লক্ষ করুন যে শেষ লাইনে কোনও উদ্ধৃতি নেই। এর কারণ আপনি শেলটি পরামিতিগুলিকে শব্দগুলিতে বিভক্ত করতে চান ( আপনার প্রোগ্রামে পৃথক যুক্তি দিতে --flag1এবং দিতে $1)। অবশ্যই, যদি আপনার মূল পরামিতিগুলিতে ফাঁক থাকে তবে এটি ভুল হয়ে যাবে। আপনি যদি এটি চালাচ্ছেন, তবে আপনি এটি ছেড়ে দিতে পারেন, তবে এটি যদি একটি সাধারণ স্ক্রিপ্ট হয়, যদি ব্যবহারকারী শূণ্যস্থান দিয়ে কিছু প্রবেশ করে তবে এর অপ্রত্যাশিত আচরণ থাকতে পারে। এটি পরিচালনা করতে আপনাকে কোডটি কিছুটা কৃপণ করে তুলতে হবে।

xমধ্যে উপসর্গ []পরীক্ষা ক্ষেত্রে নেই $3বা $4খালি। সেক্ষেত্রে বাশ প্রসারিত [ FALSE != $3 ]হবে [ FALSE != ]যা একটি সিনট্যাক্স ত্রুটি, সুতরাং এর বিরুদ্ধে রক্ষা করার জন্য আরও একটি নির্বিচার চরিত্র রয়েছে। এটি একটি খুব সাধারণ উপায়, আপনি এটি অনেক স্ক্রিপ্টে দেখতে পাবেন।

আমি নিশ্চিত হয়েছি OPTFLAG1এবং বাকিগুলি ""শুরুতে ঠিক নিশ্চিত করেছিলাম (যদি সেগুলি আগে কোনও কিছুতে সেট করা থাকে) তবে পরিবেশে যদি সেগুলি প্রকৃতপক্ষে ঘোষণা না করা হয়, তবে আপনাকে কঠোরভাবে এটি করার দরকার নেই।

অতিরিক্ত কয়েকটি মন্তব্য:

  • runprogramপতাকার সাথে আপনি প্যারামিটারগুলি ঠিক একইভাবে পেয়েছিলেন : পতাকা সহ। এটাই John Nকথা বলছে। এটিই getoptsদরকারী হয়ে ওঠে।
  • এই উদ্দেশ্যে মিথ্যা ব্যবহার করা কিছুটা মানহীন এবং বেশ দীর্ঘ। সাধারণত, -একটি খালি মান সিগন্যাল করতে একটি অক্ষর (সম্ভবত ) ব্যবহার করতে পারে , বা কেবল একটি খালি স্ট্রিং পাস করতে পারে "", যদি তা না হলে প্যারামিটারের বৈধ মান না হয়। খালি স্ট্রিং পরীক্ষাকে আরও খাটো করে তোলে, কেবল ব্যবহার করুন if [ -n "$3" ]
  • যদি কেবলমাত্র একটি optionচ্ছিক পতাকা রয়েছে, বা যদি সেগুলি নির্ভরশীল হয় তবে আপনার কখনই অপ্টফ্ল্যাজি 2 থাকতে পারে না, তবে ওপটিএফএলএজি 1 নয়, তবে আপনি যেটি সেট করতে চান না তা কেবল আপনি এড়িয়ে যেতে পারেন। আপনি যদি ""খালি প্যারামিটারগুলির জন্য ব্যবহার করেন , যেমন উপরে প্রস্তাবিত, আপনি যাইহোক যাইহোক সমস্ত ট্রেলিং শূন্যস্থানগুলি এড়িয়ে যেতে পারেন।

এই পদ্ধতিটি মেকফিলগুলিতে সংকলকগুলিতে বিকল্পগুলি যেভাবে পাস করা হয় তা বেশ।

এবং আবারও - যদি ইনপুটগুলিতে স্পেস থাকতে পারে তবে এটি কুরুচিপূর্ণ হয়।


না, আপনি শেলটি পরামিতিগুলিকে শব্দগুলিতে বিভক্ত করতে চান না। আপনার কাছে সর্বদা শেল ভেরিয়েবলের সমস্ত উল্লেখ উল্লেখ করা উচিত যদি না আপনার কাছে যুক্তিসঙ্গত কারণ না থাকে এবং আপনি নিশ্চিত হন যে আপনি কী করছেন। বাশ / পসিক্স শেলগুলিতে কোনও পরিবর্তনশীল উদ্ধৃতি দিতে ব্যর্থ হওয়ার সুরক্ষা সম্পর্কিত প্রভাবগুলি দেখুন , আপনি যদি এর সাথে পরিচিত না হন এবং আমার উত্তরটিতে স্ক্রোল করুন , যেখানে আমি এই সমস্যাটি স্পষ্টভাবে সমাধান করি ( জ্যাসেন একই কৌশল ব্যবহার করে )।
জি-ম্যান বলেছেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.