বাশ / বোর্নে একটি "ইন" অপারেটর আছে?


17

আমি এমন একটি "ইন" অপারেটর খুঁজছি যা এইরকম কিছু কাজ করে:

if [ "$1" in ("cat","dog","mouse") ]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

এটি বেশ কয়েকটি "বা" পরীক্ষাগুলি ব্যবহার করে বলার চেয়ে স্পষ্টতই একটি সংক্ষিপ্ত বিবৃতি।

উত্তর:


31

আপনি ব্যবহার করতে পারেন case...esac

$ cat in.sh 
#!/bin/bash

case "$1" in 
  "cat"|"dog"|"mouse")
    echo "dollar 1 is either a cat or a dog or a mouse"
  ;;
  *)
    echo "none of the above"
  ;;
esac

যাত্রা।

$ ./in.sh dog
dollar 1 is either a cat or a dog or a mouse
$ ./in.sh hamster
none of the above

সহ ksh, bash -O extglobবা zsh -o kshglob, আপনি একটি বর্ধিত গ্লোব প্যাটার্ন ব্যবহার করতে পারেন:

if [[ "$1" = @(cat|dog|mouse) ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

সহ bash, ksh93বা zsh, আপনি একটি নিয়মিত প্রকাশের তুলনাও ব্যবহার করতে পারেন:

if [[ "$1" =~ ^(cat|dog|mouse)$ ]]; then
  echo "dollar 1 is either a cat or a dog or a mouse"
else
  echo "none of the above"
fi

ডাবল বন্ধনী জন্য কোন কারণ? আবার ধন্যবাদ!
মির্জয়বিপার

1
@ শ্রীজাইভিপার ডাবল বন্ধনীগুলি একটি বর্ধিত পরীক্ষামূলক =~
কাঠামো

1
@ স্টিল্ড্রাইভার কেবল পসিক্স [, তবে [[বাশ, কেএসএসের বর্ধিত বৈশিষ্ট্য রয়েছে (সম্ভবত এটি সেখান থেকে উদ্ভূত হয়েছে, এবং zsh। caseউদাহরণস্বরূপ সবার মধ্যে বেশিরভাগ
পসিক্স

2
@ স্টাফেনচেজেলস যেহেতু কমপক্ষে 4.1-আলফা বাশ স্পষ্টভাবে এক্সট্লগ সেট করার দরকার নেই। বাশ পরিবর্তন থেকে : এস। সামঞ্জস্যের জন্য অস্ট্রেলিয়াকে অস্থায়ীভাবে জোর করুন যখন == এবং! = অপারেটরের সাথে প্যাটার্ন আর্গুমেন্টকে [[কমান্ডের সাথে সামঞ্জস্য করার জন্য) পার্স করুন।
ইসহাক

@ স্টিলড্রাইভার $ 1 in case "$1" inকে উদ্ধৃত করার দরকার নেই, সেই টোকেনে কোনও শব্দ বিভাজন বা পথের নাম প্রসারিত হবে না।
ইসহাক

9

বাশে কোনও "ইন" পরীক্ষা নেই, তবে একটি রেজেক্স পরীক্ষা রয়েছে (বোর্নে নয়):

if [[ $1 =~ ^(cat|dog|mouse)$ ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

এবং সাধারণত একটি ভেরিয়েবল ব্যবহার করে লেখা হয় (উদ্ধৃতি সহ কম সমস্যা):

regex='^(cat|dog|mouse)$'

if [[ $1 =~ $regex ]]; then
    echo "dollar 1 is either a cat or a dog or a mouse"
fi

পুরনো বোর্ন শেলের জন্য আপনার কেস ম্যাচটি ব্যবহার করতে হবে:

case $1 in
    cat|dog|mouse)   echo "dollar 1 is either a cat or a dog or a mouse";;
esac

এটি আমার কাছে গৃহীত উত্তর।
নম জি ভিইউ

6

caseআপনার যদি পোষা প্রাণীগুলির বিরুদ্ধে একটি নির্দিষ্ট সেট থাকে যার সাথে আপনি ম্যাচ করতে চান তবে একটি জাল ব্যবহার করা ভাল well আপনার রানটাইমের সময় যেমন প্যাটার্নটি তৈরি করতে হবে তবে এটি কাজ করবে নাcase প্রসারিত পরামিতিগুলির মধ্যে থেকে বিকল্পটির ব্যাখ্যা দেয় না।

এটি কেবল আক্ষরিক স্ট্রিংয়ের সাথে মিলবে cat|dog|mouse:

patt='cat|dog|mouse'
case $1 in 
        $patt) echo "$1 matches the case" ;; 
esac

আপনি তবে নিয়মিত এক্সপ্রেশন ম্যাচের সাথে একটি ভেরিয়েবল ব্যবহার করতে পারেন। যতক্ষণ ভেরিয়েবল উদ্ধৃত হয় না, ততক্ষণ এর মধ্যে থাকা কোনও রেজেক্স অপারেটরগুলির বিশেষ অর্থ রয়েছে।

patt='cat|dog|mouse'
if [[ "$1" =~ ^($patt)$ ]]; then
        echo "$1 matches the pattern"
fi

আপনি সহযোগী অ্যারেগুলিও ব্যবহার করতে পারেন। কোনওটিতে কী রয়েছে কিনা তা পরীক্ষা করা কোনও inঅপারেটরের নিকটতম জিনিস যা বাশ দেয়। যদিও সিনট্যাক্সটি কিছুটা কুৎসিত:

declare -A arr
arr[cat]=1
arr[dog]=1
arr[mouse]=1

if [ "${arr[$1]+x}" ]; then
        echo "$1 is in the array"
fi

( সেট ${arr[$1]+x}করা xথাকলে প্রসারিত হয় arr[$1], অন্যথায় খালি। )


5

আপনি পারেcase একটি ifপরীক্ষায় একটি বিবৃতি ব্যবহার পারেন , তবে কোডটি কিছুটা লোমশ দেখাচ্ছে:

if case "$1" in (cat|dog|mouse) true ;; (*) false; esac; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

বা কিছুটা ছোট

if ! case "$1" in (cat|dog|mouse) false; esac; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

এটির জন্য caseপ্যাটার্ন মেলানোর জন্য একটি ধারা ব্যবহার করছেif । এটি একটি অপ্রয়োজনীয় সত্য / মিথ্যা পরীক্ষার পরিচয় দেয়।

এটি কেবল ব্যবহার করা ভাল case:

case "$1" in
    cat|dog|mouse)
        printf '"%s" is one of cat, dog or mouse\n' "$1"
        ;;
    *)
        printf '"%s" is unknown\n' "$1"
esac

এটি করবেন না:

is_one_of () {
    eval "case $1 in ($2) return 0; esac"
    return 1
}

if is_one_of "$1" 'cat|dog|mouse'; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

অথবা এটা:

is_one_of () (
    word=$1
    shift
    IFS='|'
    eval "case $word in ($*) return 0; esac"
    return 1
)

if is_one_of "$1" cat dog mouse; then
    printf '"%s" is one of cat, dog or mouse\n' "$1"
else
    printf '"%s" is unknown\n' "$1"
fi

... কারণ আপনি কেবলমাত্র আরও বিপজ্জনক ক্রাফ্ট যুক্ত করছেন, কেবলমাত্র ifএকটি যুক্তিসঙ্গত caseবিবরণের জায়গায় আপনার কোডে একটি বিবৃতি ব্যবহার করতে সক্ষম হতে ।


ফাংশন কলের ক্ষেত্রে কেস বিভক্ত করা এবং যদি স্টেটমেন্টের অভ্যন্তরে প্রস্থান স্থিতির মূল্যায়ন করা ভাল না হয়?
সের্গেই কোলোডিয়াজনি

@ সের্গি কলোডিএজনি এবং প্যাটার্নটি কার্যকারণের পক্ষে যুক্তি হয়ে উঠুক? এটি একটি কি করতে হবে evalএর caseযে ক্ষেত্রে বিবৃতি, এবং এটি আরও বেশি ত্রুটি প্রবণ হবে।
কুসালানন্দ

এক্ষেত্রে সহজ প্যাটার্ন রয়েছে, প্রতিটি ফাংশন করতে এবং করতে পজিশনাল প্যারামিটার হিসাবে পাস হতে পারে "$1"|"$2"|"$3"। এছাড়াও unix.stackexchange.com/a/234415/85039 তবে হ্যাঁ, এটি কিছুটা লোমশ।
সের্গেই কোলোডিয়াজনি

4

grep কাছে।

if echo $1 | grep -qE "^(cat|dog|mouse)$"; then 
    echo "dollar 1 is either a cat or a dog or a mouse"
fi
  • -qস্ক্রিনে কোনও আউটপুট এড়াতে (এর চেয়ে দ্রুত টাইপ করা >/dev/null)।
  • -Eবর্ধিত নিয়মিত এক্সপ্রেশন (cat|dog|mouse)দিকগুলির জন্য এটির প্রয়োজন।
  • ^(cat|dog|mouse)$^বিড়াল, কুকুর বা মাউসের সাথে ( ) শুরু হওয়া কোনও লাইন মেলে ( (cat|dog|mouse)) তারপরে লাইনের শেষে ( $)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.