কেস শর্ত হিসাবে আমি কীভাবে একটি পরিবর্তনশীল ব্যবহার করতে পারি?


17

আমি স্টেটমেন্ট টেস্ট |হিসাবে পৃথক স্ট্রিং সমন্বিত একটি ভেরিয়েবল ব্যবহার করার চেষ্টা করছি case। উদাহরণ স্বরূপ:

string="\"foo\"|\"bar\""
read choice
case $choice in
    $string)
        echo "You chose $choice";;
    *)
        echo "Bad choice!";;
esac

আমি বিবৃতিটির প্রথম অংশটি টাইপ করতে fooবা barপ্রয়োগ করতে সক্ষম হতে চাই case। তবে উভয়ই fooএবং barআমাকে দ্বিতীয়টিতে নিয়ে যান:

$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!

"$string"পরিবর্তে ব্যবহার করে $stringকোনও তফাত হয় না। উভয়ই ব্যবহার করে না string="foo|bar"

আমি জানি আমি এটি এইভাবে করতে পারি:

case $choice in
    "foo"|"bar")
        echo "You chose $choice";;
    *)
        echo "Bad choice!";;
esac

আমি বিভিন্ন কর্মক্ষেত্রের কথা ভাবতে পারি তবে caseবাশ-এর ​​শর্ত হিসাবে ভেরিয়েবল ব্যবহার করা সম্ভব কিনা তা আমি জানতে চাই । এটি কি সম্ভব এবং যদি তা হয় তবে কীভাবে?


2
আমি একটি বাস্তব উত্তর যেমন সুপারিশ নিজেকে আনতে পারবেন না, কিন্তু যেহেতু অন্য কোন এক এটি উল্লিখিত হলে, আপনি পারে একটি ইন কেস বিবৃতি মোড়ানো eval, $ পছন্দ, ডান বন্ধনী, তারকাচিহ্ন, সেমিকোলন, এবং নতুন লাইন পলায়নের। কুরুচিপূর্ণ, তবে এটি "কাজ করে"।
জেফ শ্যাচলার

@ জেফশালার - এটি অনেক সময় খারাপ ধারণা নয় এবং সম্ভবত এই ক্ষেত্রে কেবল টিকিট। আমি এটির সুপারিশও বিবেচনা করেছি, তবে readকিছুটা আমাকে থামিয়ে দিয়েছে। আমার মতে ব্যবহারকারীর ইনপুট বৈধতা, যা কি এই উপস্থিত হতে পারে হয়, caseনিদর্শন উচিত নয় মূল্যায়ন তালিকার শীর্ষে হতে, এবং বদলে নিচে ছেঁটে দিতে হবে *ডিফল্ট প্যাটার্ন যেমন যে শুধুমাত্র ফলাফল সেখানে পৌঁছানোর গ্রহণযোগ্য গ্যারান্টী আছে। তবুও, কারণ সমস্যাটি পার্স / এক্সপেনশন অর্ডার, তারপরে দ্বিতীয় মূল্যায়নটি যা ডাকা হবে তা হতে পারে।
মাইক্রজারভ

উত্তর:


14

বাশ ম্যানুয়ালটিতে বলা হয়েছে:

কেস শব্দটি [[(প্যাটার্ন [| প্যাটার্ন] ...) তালিকায় ;; ] ... এস্যাক

প্রতিটি পরীক্ষা করা প্যাটার্নটি টিলডে সম্প্রসারণ, পরামিতি এবং পরিবর্তনশীল সম্প্রসারণ, পাটিগণিত প্রতিস্থাপন, কমান্ড প্রতিস্থাপন এবং প্রক্রিয়া বিকল্প ব্যবহার করে প্রসারিত করা হয়।

না «পথের নাম সম্প্রসারণ

সুতরাং: কোনও প্যাটার্নটি «পথের নাম সম্প্রসারণ with দিয়ে প্রসারিত হয় না»

অতএব: একটি প্যাটার্নে "|" থাকতে পারে না ভিতরে। কেবলমাত্র: "|" এর সাথে দুটি নিদর্শন যুক্ত হতে পারে।

এইটা কাজ করে:

s1="foo"; s2="bar"    # or even s1="*foo*"; s2="*bar*"

read choice
case $choice in
    $s1|$s2 )     echo "Two val choice $choice"; ;;  # not "$s1"|"$s2"
    * )           echo "A Bad  choice! $choice"; ;;
esac

«বর্ধিত গ্লোববিং Using ব্যবহার করে

তবে, «পথের নাম সম্প্রসারণ» নিয়ম ব্যবহার করে wordমিলছে pattern
এবং এখানে «বর্ধিত গ্লোববিং , এখানে এবং এখানে বিকল্প (" | ") নিদর্শন ব্যবহারের অনুমতি দেয়।

এটিও কাজ করে:

shopt -s extglob

string='@(foo|bar)'

read choice
    case $choice in
        $string )      printf 'String  choice %-20s' "$choice"; ;;&
        $s1|$s2 )      printf 'Two val choice %-20s' "$choice"; ;;
        *)             printf 'A Bad  choice! %-20s' "$choice"; ;;
    esac
echo

স্ট্রিং সামগ্রী

পরবর্তী পরীক্ষার স্ক্রিপ্টটি দেখায় যে যে প্যাটার্নটি সমস্ত লাইনগুলির সাথে মেলে যা কোনও fooবা অন্য barকোথাও রয়েছে '*$(foo|bar)*'বা দুটি ভেরিয়েবল $s1=*foo*এবং$s2=*bar*


পরীক্ষার স্ক্রিপ্ট:

shopt -s extglob    # comment out this line to test unset extglob.
shopt -p extglob

s1="*foo*"; s2="*bar*"

string="*foo*"
string="*foo*|*bar*"
string='@(*foo*|*bar)'
string='*@(foo|bar)*'
printf "%s\n" "$string"

while IFS= read -r choice; do
    case $choice in
        "$s1"|"$s2" )   printf 'A first choice %-20s' "$choice"; ;;&
        $string )   printf 'String  choice %-20s' "$choice"; ;;&
        $s1|$s2 )   printf 'Two val choice %-20s' "$choice"; ;;
        *)      printf 'A Bad  choice! %-20s' "$choice"; ;;
    esac
    echo
done <<-\_several_strings_
f
b
foo
bar
*foo*
*foo*|*bar*
\"foo\"
"foo"
afooline
onebarvalue
now foo with spaces
_several_strings_

9

আপনি extglobবিকল্পটি ব্যবহার করতে পারেন :

shopt -s extglob
string='@(foo|bar)'

মজাদার; কি @(foo|bar)তুলনায় বিশেষ করে তোলে foo|bar? উভয়ই বৈধ নিদর্শন যা অক্ষরে টাইপ করার সময় একই কাজ করে।
চ্যানার

4
আহ, কিছু মনে করবেন না। |প্যাটার্নটির অংশ নয় foo|bar, এটি একটি ধারাতে caseএকাধিক নিদর্শনগুলিকে অনুমতি দেওয়ার জন্য বিবৃতিটির বাক্য গঠনের অংশ । | হয় যদিও, বর্ধিত প্যাটার্ন অংশ।
চ্যানার

3

আপনার জন্য দুটি ভেরিয়েবল দরকার caseকারণ নিদর্শনগুলি প্রসারিত |হওয়ার আগে বা পাইপটি পার্স করা হয়েছে।

v1=foo v2=bar

case foo in ("$v1"|"$v2") echo foo; esac

foo

ভেরিয়েবলের শেল প্যাটার্নগুলি যখন উদ্ধৃত বা উদ্ধৃত না হয় পাশাপাশি আলাদাভাবে পরিচালনা করা হয়:

q=?

case a in
("$q") echo question mark;;
($q)   echo not a question mark
esac

not a question mark

-1

আপনি যদি কোনও ড্যাশ-সামঞ্জস্যপূর্ণ কাজ করতে চান তবে আপনি লিখতে পারেন:

  string="foo|bar"
  read choice
  awk 'BEGIN{
   n=split("'$string'",p,"|");
   for(i=1;i<=n;i++)
    if(system("\
      case \"'$choice'\" in "p[i]")\
       echo \"You chose '$choice'\";\
       exit 1;;\
      esac"))
     exit;
   print "Bad choice"
  }'

ব্যাখ্যা: awk "স্ট্রিং" বিভক্ত করতে এবং প্রতিটি অংশ পৃথকভাবে পরীক্ষা করতে ব্যবহৃত হয়। যদি "পছন্দ" বর্তমানে পরীক্ষিত অংশ পি এর সাথে মেলে, তবে awk-কমান্ডটি 11 লাইনের "প্রস্থান" দিয়ে শেষ হবে খুব পরীক্ষার জন্য, শেলের "কেস" ব্যবহার করা হয় (একটি 'সিস্টেম'-কলের মধ্যে) , যেমন টেরডন জিজ্ঞাসা করেছেন। এটি শেলটির "কেস" অনুমতি দেয় বলে "foooo" ("অনুসন্ধানের প্যাটার্ন") এর সাথে মিলে যাওয়ার জন্য উদাহরণস্বরূপ "foo * | বার" হিসাবে পরীক্ষিত "স্ট্রিং" পরিবর্তন করার সম্ভাবনা রাখে। পরিবর্তে আপনি যদি নিয়মিত ভাবটি পছন্দ করেন তবে আপনি "সিস্টেম" -ক্যালটি বাদ দিতে পারেন এবং তার পরিবর্তে awk এর "~" বা "ম্যাচ" ব্যবহার করতে পারেন।


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