অন্য ভেরিয়েবলের উপর নির্ভর করে আমি কীভাবে সংক্ষিপ্তভাবে একটি ভেরিয়েবলের বিভিন্ন মান নির্ধারণ করতে পারি?


20

আমি কীভাবে এই শেল স্ক্রিপ্টটি সংক্ষিপ্ত করতে পারি?

CODE="A"

if test "$CODE" = "A"
then
 PN="com.tencent.ig"
elif test "$CODE" = "a"
 then
 PN="com.tencent.ig"
elif test "$CODE" = "B"
 then
 PN="com.vng.pubgmobile"
elif test "$CODE" = "b"
 then
 PN="com.vng.pubgmobile"
elif test "$CODE" = "C"
 then
 PN="com.pubg.krmobile"
elif test "$CODE" = "c"
 then
 PN="com.pubg.krmobile"
elif test "$CODE" = "D"
 then
 PN="com.rekoo.pubgm"
elif test "$CODE" = "d"
 then
 PN="com.rekoo.pubgm"
else
 echo -e "\a\t ERROR!"
 echo -e "\a\t CODE KOSONG"
 echo -e "\a\t MELAKUKAN EXIT OTOMATIS"
 exit
fi

2
আমি মনে করি এটি bashকোড? নাকি আপনার মনে অন্য কোনও শেল আছে?
ফ্রেডি

3
ভবিষ্যতে এফওয়াইআই, আমি ইউআরএল এবং অন্যান্য জিনিসগুলির মতো ব্যক্তিগত তথ্য "com.hello.world" এর মতো জেনেরিক কিছু দিয়ে প্রতিস্থাপন করার পরামর্শ দেব।
ট্রেভর বয়েড স্মিথ

1
@ আইসোমোনিআইআই আপনার পরিবর্তে কোডগলফ.এসই জিজ্ঞাসা করা উচিত: পি
ম্যাকিচিজ 21

3
@ ট্রেভর, আমি সুপারিশ করব example.org, example.netইত্যাদি, কারণ এই ডোমেনগুলি বিশেষত আরএফসি 2606 এ এই উদ্দেশ্যে সংরক্ষিত এবং কখনই আসল সত্তার জন্য ব্যবহৃত হবে না।
টবি স্পিড

2
"হ্যালো.কম" গুগলের মালিকানাযুক্ত হওয়ায় @ ট্রেভরবয়েডস্মিথ সেকেন্ডিং টবির কম.এক্সেমেল ইত্যাদির সুপারিশ।
ডেভিড কনরাড

উত্তর:


61

একটি caseবিবৃতি ব্যবহার করুন (বহনযোগ্য, যে কোনও shসদৃশ শেলের মধ্যে কাজ করে ):

case "$CODE" in
    [aA] ) PN="com.tencent.ig" ;;
    [bB] ) PN="com.vng.pubgmobile" ;;
    [cC] ) PN="com.pubg.krmobile" ;;
    [dD] ) PN="com.rekoo.pubgm" ;;
    * ) printf '\a\t%s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS' >&2
        exit 1 ;;
esac

আমি আপনার সমস্ত পরিবর্তনশীল নামগুলি সমস্ত মূল অক্ষর (যেমন CODE) থেকে ছোট বা মিক্সড-কেস (যেমন codeবা Code) তে পরিবর্তন করার পরামর্শ দিই । অনেকগুলি অল-ক্যাপের নাম রয়েছে যার বিশেষ অর্থ রয়েছে এবং এগুলির মধ্যে একটির দুর্ঘটনাক্রমে পুনরায় ব্যবহার করা সমস্যার কারণ হতে পারে।

অন্যান্য নোট: স্ট্যান্ডার্ড কনভেনশনটি হ'ল "স্ট্যান্ডার্ড আউটপুট" এর পরিবর্তে "স্ট্যান্ডার্ড ত্রুটি" এ ত্রুটি বার্তা প্রেরণ করা; >&2পুনর্নির্দেশ এই আছে। এছাড়াও, যদি কোনও স্ক্রিপ্ট (বা প্রোগ্রাম) ব্যর্থ হয় তবে ননজারো স্থিতি ( exit 1) সহ প্রস্থান করা ভাল , সুতরাং যে কোনও কলিং প্রসঙ্গটি কী ভুল হয়েছে তা বলতে পারে। এছাড়া বিভিন্ন সমস্যা নির্দেশ করে (এর "exit কোডগুলি" বিভাগে দেখতে বিভিন্ন স্থিতিগুলিকে ব্যবহার করা সম্ভব man পৃষ্ঠা একটি ভাল উদাহরণ জন্য)। (এখানে পরামর্শের জন্য স্টাফেন চেজেলাস এবং মন্টি হার্ডারের কাছে ক্রেডিট)curl

আমি (এবং ) এর printfপরিবর্তে প্রস্তাব দিচ্ছি , কারণ এটি ওএস, সংস্করণ, সেটিংস ইত্যাদির মধ্যে আরও বহনযোগ্য। আমি একবারে আমার স্ক্রিপ্টগুলির একটি গুচ্ছটি ভেঙে ফেলেছিলাম কারণ একটি ওএস আপডেটে বিভিন্ন বিকল্পের সাথে সংকলিত বাশের একটি সংস্করণ অন্তর্ভুক্ত ছিল, যা কীভাবে আচরণ করে তা পরিবর্তন করে ।echo -eecho -necho

আশেপাশে ডাবল-কোটগুলির $CODEপ্রয়োজন নেই। স্ট্রিং এ caseএর কয়েকটি প্রসঙ্গ যেখানে সেগুলি ছেড়ে দেওয়া নিরাপদ। যাইহোক, আমি পরিবর্তনশীল উল্লেখগুলি ডাবল-কোয়েট করতে পছন্দ করি যদি না নির্দিষ্ট কারণ হয় কারণ এটি নিরাপদ কোথায় এবং এটি কোথায় নেই সে সম্পর্কে নজর রাখা শক্ত, সুতরাং কেবল সেগুলি অভ্যাসগতভাবে দ্বিগুণ-উদ্ধৃতি করা নিরাপদ।


5
@ আইসোমআইনিআইআই এটি হিসাবে গণনা করা হবে *(এবং ত্রুটিটি প্রিন্ট করুন) - প্যাটার্নটি [aA]"এ" বা "এ" এর সাথে মেলে তবে দু'জনেই একসাথে নয়।
গর্ডন ডেভিসন

6
এটি করার ঠিক সঠিক উপায় এটি হ'ল শেষে ওয়াইল্ডকার্ডে তার আউটপুটটিকে স্ট্ডারের দিকে পুনঃনির্দেশিত করা এবং একটি শূন্য-বহির্গমন প্রস্থান মান উত্পন্ন করা। একমাত্র যেটির পরিবর্তনের প্রয়োজন হতে পারে তা হ'ল প্রস্থান মান, কারণ ফিরে আসতে একাধিক ত্রুটি থাকতে পারে। বৃহত্তর স্ক্রিপ্টে, এমন একটি বিভাগ থাকতে পারে (সম্ভবত অন্য কোনও ফাইল থেকে উত্সযুক্ত) যা প্রস্থান ভেলগুলি সংজ্ঞায়িত করে readonly Exit_BadCode=1যাতে এটি exit $Exit_BadCodeপরিবর্তে বলতে পারে ।
মন্টি হার্ডার

2
একটি সাম্প্রতিক ব্যাশ সাথে যাচ্ছেন, তাহলে ব্যবহার case "${CODE,}" in, তাই কন্ডিশন প্রতিটি কেবল উঠবে যে a), b)ইত্যাদি
স্টিভ

2
@ মন্টিহার্ডার এটি নির্ভর করে যদি এই কোডগুলির কয়েক শত থাকে তবে প্রতিটি স্ট্রিংয়ের সাথে সংশ্লিষ্ট, তবে অন্য একটি পদ্ধতির আরও ভাল হতে পারে। হাতের সঠিক সমস্যার জন্য, এটি যথেষ্ট।
কুসালানন্দ

2
@ মন্টিহার্ডার দুঃখিত, আমার আরও পরিষ্কার হওয়া উচিত ছিল। "কোড" দ্বারা আমি বোঝাতে চাইছি $CODE। আমি সবসময় "প্রস্থান স্থিতি" কল করি, ঠিক কখনই "কোড" হয় না। যদি স্ক্রিপ্টটিতে স্ট্রিংগুলি উল্লেখ করতে অনেক শত কী ব্যবহার করতে হয় তবে একটি caseবিবৃতি ব্যবহার করা অনর্থক হয়ে যায়।
কুসালানন্দ

19

ধরে নিচ্ছি আপনি bashরিলিজ ৪.০ বা আরও নতুন ব্যবহার করছেন ...

CODE=A

declare -A domain

domain=(
   [a]=com.tencent.ig
   [b]=com.vng.pubgmobile
   [c]=com.pubg.krmobile
   [d]=com.rekoo.pubgm
)

PN=${domain[${CODE,,}]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

কোডটিতে, আমি একটি ডোমেনির সমস্ত অক্ষর সমন্বিত একটি অ্যারেসিয়েটিভ অ্যারে সংজ্ঞায়িত করি, প্রতিটি একক অক্ষরের লোয়ার-কেসের সাথে যুক্ত।

$PNপরিবর্তনশীল ডোমেইন নাম কম cased সংশ্লিষ্ট নির্ধারিত হয় $CODEমান ( ${CODE,,}রিটার্ন মান $CODEশুধুমাত্র ছোট হাতের অক্ষর পরিণত) এই অ্যারে থেকে, কিন্তু যদি $CODEএকটি বৈধ এন্ট্রি সঙ্গে সঙ্গতিপূর্ণ নয় domainতালিকা, এটি একটি সহ স্ক্রিপ্টের প্রস্থান করে ত্রুটি.

${variable:?error message}পরামিতি প্রতিকল্পন মান প্রসারিত হবে $variable(কোড যথাযথ ডোমেন) কিন্তু ত্রুটি বার্তা সহ স্ক্রিপ্ট থেকে প্রস্থান করবে মান খালি পাওয়া যায় না। আপনি আপনার কোডের মতো ত্রুটি বার্তার হুবহু একই বিন্যাসটি পান না তবে অবৈধ হলে এটি মূলত একই আচরণ করবে $CODE:

$ bash script.sh
script.sh: line 12: domain[${CODE,,}]: ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS

আপনি যদি চরিত্র গণনা সম্পর্কে যত্নশীল হন তবে আমরা এটি আরও সংক্ষিপ্ত করে তুলতে পারি:

CODE=A
declare -A domain=( [a]=tencent.ig [b]=vng.pubgmobile [c]=pubg.krmobile [d]=rekoo.pubgm )
PN=com.${domain[${CODE,,}]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

অপ্রয়োজনীয় নিউলাইনগুলি মোছা ছাড়াও, আমি com.প্রতিটি ডোমেন থেকেও সরিয়েছি (এটি পরিবর্তে নিয়োগের ক্ষেত্রে যুক্ত করা হয় PN)।

নোট করুন যে উপরের সমস্ত কোড এমনকি একাধিক অক্ষরের মানের জন্যও কাজ করবে $CODE(যদি domainঅ্যারেতে এর জন্য নিম্ন-কেসযুক্ত কীগুলি বিদ্যমান থাকে )।


পরিবর্তে যদি $CODEএকটি সংখ্যাসূচক (শূন্য-ভিত্তিক) সূচক হয়, এটি কোডটি কিছুটা সরল করবে:

CODE=0

domain=( com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm )
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

এটি অতিরিক্ত domainপ্রতিটি লাইনে প্রতি একটি এন্ট্রি সহ সহায়ক ফাইল থেকে অ্যারেটি পড়া সহজ করে তোলে :

CODE=0

readarray -t domain <domains.txt
PN=${domain[CODE]:?ERROR! CODE KOSONG, MELAKUKAN EXIT OTOMATIS}

1
@ আইসোমঅনআইআই declare -A domainকেবল বলেছে এটি domainএকটি সহযোগী অ্যারে ("হ্যাশ") পরিবর্তনশীল হওয়া উচিত।
Kusalananda

1
@ আইসাক এখন আপনার থেকে আরও স্বতন্ত্র। সতর্ক থাকুন জন্য ধন্যবাদ।
কুসালানন্দ

1
Zsh বা ksh93 ব্যবহার করা ভাল। বাশের জন্য আপনার সাম্প্রতিক সংস্করণটি দরকার এবং এটি খালি মানের জন্য ব্যর্থ হবে $CODE
স্টাফেন চেজেলাস

1
@ স্টাফেনচাজলাস হ্যাঁ, আপনি যদি খারাপ $CODEসেট অ্যারে সাবস্ক্রিপ্টটি সেট না করে বা খালি রাখেন তবে একটি অতিরিক্ত ত্রুটি বার্তা পাবেন তবে এটি পরে সঠিক কাস্টম ত্রুটি বার্তা উত্পন্ন করবে।
Kusalananda

1
@ কুসালানন্দ একটি নতুন (বৈধ পসিক্স) স্ক্রিপ্ট পোস্ট করা হয়েছে। ত্রুটি ছাড়া চেক খুব সংক্ষিপ্ত।
ইসহাক

11

যদি আপনার শেলটি অ্যারেগুলিকে অনুমতি দেয় তবে সংক্ষিপ্ত উত্তরটি ব্যাশের ক্ষেত্রে এই উদাহরণের মতো হওয়া উচিত:

declare -A site
site=( [a]=com.tencent.ig [b]=com.vng.pubgmobile [c]=com.pubg.krmobile [d]=com.rekoo.pubgm )

pn=${site[${code,}]}

এটি ধরে নেওয়া হচ্ছে যে $codeকেবল a, b, c বা d হতে পারে।
যদি তা না হয় তবে একটি পরীক্ষা যুক্ত করুন:

case ${site,} in
    a|b|c|d)        pn=${site[${code,}]};;
    *)              pn="default site"
                    printf '\a\t %s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS'
                    exit 1
                    ;;
esac

যদি ইনপুটটি A হয় তবে এটি কি সেই স্ক্রিপ্টটিতে কাজ করবে? দুঃখিত আমার ইংরেজি খারাপ
IISomeOneII

2
হ্যাঁ, ${var,}প্রসারণটি এর প্রথম চরিত্রের ছোট অক্ষরে রূপান্তর করে ${var}। @ আইসমোনিআইআই
আইজাক

1
${var,}যদিও বাশ-নির্দিষ্ট বলে মনে হচ্ছে। আমি মনে করি সহযোগী অ্যারে ksh এবং zsh
তেও

@ ইলক্কাচু হ্যাঁ, উভয় গুণে সঠিক।
আইজাক

সবাইকে ধন্যবাদ, এখানে প্রচুর ভাল লোক 👍
আইআইএসোমেনআইআই

3

আমি এই উত্তরটি অন্য একটি দিক নিয়ে যাচ্ছি। স্ক্রিপ্টে আপনার ডেটা কোডিংয়ের পরিবর্তে সেই ডেটাটিকে একটি আলাদা ডেটা ফাইলে রাখুন, তারপরে ফাইলটি অনুসন্ধান করার জন্য কোডটি ব্যবহার করুন:

$ cat names.cfg 
a com.tencent.ig
b com.vng.pubgmobile
c com.pubg.krmobile
d com.rekoo.pubgm

$ cat lookup.sh
PN=$(awk -v code="${1:-}" 'tolower($1) == tolower(code) { print $2; }' names.cfg)
if [ -z "${PN}" ]; then
  printf '\a\t%s\n' 'ERROR!' 'CODE KOSONG' 'MELAKUKAN EXIT OTOMATIS' >&2
  exit 1
fi
echo "${PN}"

$ bash lookup.sh A
com.tencent.ig
$ bash lookup.sh a
com.tencent.ig
$ bash lookup.sh x
    ERROR!
    CODE KOSONG
    MELAKUKAN EXIT OTOMATIS

এই উদ্বেগগুলি পৃথক করার কয়েকটি সুবিধা রয়েছে:

  • কোড যুক্তির আশেপাশে কাজ না করে সহজেই এবং সহজভাবে ডেটা যুক্ত করুন এবং সরান।
  • অন্যান্য প্রোগ্রামগুলি ডেটা পুনরায় ব্যবহার করতে পারে যেমন একটি নির্দিষ্ট সাব ডোমেনে কত ম্যাচ রয়েছে তা গণনা করার মতো।
  • আপনার কাছে যদি ডেটাগুলির বিশাল তালিকা থাকে তবে আপনি এটি ডিস্কে বাছাই করতে পারেন lookএবং দক্ষতার সাথে এটি বাইনারি অনুসন্ধান করতে (লাইন বাই লাইন grepবা এর পরিবর্তে awk) ব্যবহার করতে পারেন

1
আপনি যদি এই পথে যান তবে আপনাকে এখনও PNসঠিক মান হিসাবে সেট করার ব্যবস্থা করতে হবে।
ইলকচাচু

1
@ ইলক্কাচু ফেয়ার পয়েন্ট। আমি ওপিতে মিস করেছি। সংশোধন।
বিশপ

2
কোড থেকে ডেটা আলাদা করার জন্য +1।
আরপ

1

আপনি মানগুলি সূচী করতে চিঠিগুলি ব্যবহার করছেন, আপনি যদি সংখ্যা ব্যবহার করতে চান তবে এটি এতটা সহজ হয়ে যায়:

code=1
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm

eval pn\=\${"$code"}

এটি পোর্টেবল শেল কোড, বেশিরভাগ শেলগুলিতে কাজ করবে।
ব্যাশ জন্য আপনি ব্যবহার করতে পারেন: pn=${!code}, অথবা ব্যাশ / ksh / zsh ব্যবহারের জন্য: pn=${@:code:1}

অক্ষর

আপনার যদি অবশ্যই ব্যবহারকারীর চিঠিগুলি (a থেকে z, বা A থেকে Z) থাকে তবে সেগুলি অবশ্যই একটি সূচীতে রূপান্তর করতে হবে:

code=a                              # or A, B, C, ... etc.
set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\"\${$(( ($(printf '%d' "'$code")|32)-96  ))}\"

প্রতিটি অংশের উদ্দেশ্য এবং অর্থ পরিষ্কার করার জন্য একটি দীর্ঘ কোডে:

code=A

set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm

asciival=$(( $(printf '%d' "'$code") ))      # byte value of the ASCII letter.
upperval=$(( asciival |  32 ))               # shift to uppercase.
indexval=$(( upperval -  96 ))               # convert to an index from a=1.
eval arg\=\"\$\{$indexval\}\"                # the argument at such index.

আপনি যদি ছোট হাতের মানগুলিতে রূপান্তর করতে চান তবে ব্যবহার করুন: $(( asciival & ~32 ))(নিশ্চিত করুন যে আসকি মানের 6 বিটটি আনসেট নেই)।

ভুল সংকেত

আপনার স্ক্রিপ্ট কোনও ত্রুটিতে মুদ্রণ করে আউটপুট বেশ দীর্ঘ (এবং বিশেষ)।
এটির সাথে মোকাবিলা করার সর্বাধিক বহুমুখী উপায় হ'ল কোনও ফাংশনকে সংজ্ঞায়িত করা:

errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }

এবং তারপরে আপনার প্রয়োজনীয় নির্দিষ্ট বার্তা (গুলি) দিয়ে সেই ফাংশনটিকে কল করুন।

errorcode 27  "ERROR!" "CODE KOSONG" "MELAKUKAN EXIT OTOMATIS"

নোট করুন যে ফলাফলটি প্রস্থান করার মান দ্বারা দেওয়া হয়েছে exitcode(উদাহরণস্বরূপ এখানে 27)।

একটি সম্পূর্ণ স্ক্রিপ্ট (ত্রুটি পরীক্ষা করে) এর পরে হয়ে যায়:

errorcode(){ exitcode=$1; shift; printf '\a\t %s\n' "$@"; exit "$exitcode"; }

code=${1:-A}

case "$code" in 
    [a-d]|[A-D]) : ;;
    *)           errorcode 27  "ERROR!" "CODE KOSONG" "MELAKUKAN EXIT OTOMATIS" ;;
esac

set -- com.tencent.ig com.vng.pubgmobile com.pubg.krmobile com.rekoo.pubgm
eval pn\=\"\${$(( ($(printf '%d' "'$code") & ~32) - 64  ))}\"

printf 'Code=%s Argument=%s\n' "$code" "$pn"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.