যদি অন্য বিবৃতিটি যৌক্তিক এবং && বা || এবং আমি অন্যের তুলনায় কোথায় পছন্দ করব?


27

আমি সিদ্ধান্ত গ্রহণের কাঠামো সম্পর্কে শিখছি এবং আমি এই কোডগুলি জুড়ে এসেছি:

if [ -f ./myfile ]
then
     cat ./myfile
else
     cat /home/user/myfile
fi


[ -f ./myfile ] &&
cat ./myfile ||
cat /home/user/myfile

দু'জনেই একই আচরণ করে। অন্য উপায় থেকে এক উপায় ব্যবহার করার কি কোনও সুবিধা আছে?



3
তারা সমতুল্য নয় । ইকারাসের চমৎকার উত্তরটি দেখুন। উদাহরণস্বরূপ, কেসটি বিবেচনা করুন যা। / মাইফাইল বিদ্যমান তবে পঠনযোগ্য নয়।
অ্যালেক্সপি


উত্তর:


26

না, বাক্য if A; then B; else C; fiএবং A && B || Cহয় সমতুল্য

সঙ্গে if A; then B; else C; fi, কমান্ড Aসবসময় মূল্যায়ন এবং মৃত্যুদন্ড কার্যকর করা হয় (অন্তত একটি চালানো এটি তৈরি করা হয় প্রয়াস) এবং তারপর পারেন কমান্ড Bবা কমান্ড Cমূল্যায়ন এবং মৃত্যুদন্ড কার্যকর করা হয়।

সহ A && B || C, কমান্ডগুলির জন্য এটি একই Aএবং এর Bজন্য পৃথক C: কমান্ডটি ব্যর্থ হয় বা ব্যর্থ হলে কমান্ডটি Cমূল্যায়ন করা হয় এবং কার্যকর করা হয়A B

আপনার উদাহরণে, ধরুন আপনি chmod u-r ./myfile, [ -f ./myfile ]সফল হওয়া সত্ত্বেও , আপনি পাবেনcat /home/user/myfile

আমার পরামর্শ: আপনি যা চান A && Bবা ব্যবহার করুন A || B, এটি পড়তে এবং বুঝতে সহজ হয় এবং কোনও ফাঁদ নেই। তবে যদি আপনি বোঝাতে চান ... তবে ... অন্য ... তাহলে ব্যবহার করুন if A; then B; else C; fi


29

বেশিরভাগ লোক if... then... else... fiফর্মটি বোঝা সহজ করে থাকেন ।

জন্য a && b || c, আপনি নিশ্চিত যে bসত্য ফিরে আসে। এটি সূক্ষ্ম বাগের কারণ এবং এই স্টাইলটি এড়ানোর একটি ভাল কারণ। যদি খ সত্য না ফিরে আসে তবে এগুলি এক নয়।

 $ if true; then false ; else echo boom ; fi
 $ true && false || echo boom
 boom

খুব সংক্ষিপ্ত পরীক্ষা এবং ক্রিয়াগুলির জন্য যার অন্য কোনও ধারা নেই, সংক্ষিপ্ত দৈর্ঘ্য আকর্ষণীয়, যেমন

 die(){ printf "%s: %s\n" "$0" "$*" >&2 ; exit 1; }

 [ "$#" -eq 2] || die "Needs 2 arguments, input and output"

 if [ "$#" -ne 2 ] ; then
     die "Needs 2 arguments, input and output"
 fi

&&এবং ||হয় short circuiting operators, যত তাড়াতাড়ি ফলাফলের পরিচিত হয় আরও অপ্রয়োজনীয় পরীক্ষা এড়ানো হয়েছে হয়। a && b || cহিসাবে গ্রুপ করা হয় (a && b) || c। প্রথম aরান। এটি যদি fails0 এর প্রস্থান স্থিতি ফিরে না হিসাবে সংজ্ঞায়িত হয় তবে গোষ্ঠীটি (a && b)পরিচিত failএবং bএটি চালানোর প্রয়োজন নেই does ||জানে না প্রকাশের ফলাফলের তাই চালানো দরকার c। যদি aসফল হয় (শূন্যটি প্রত্যাবর্তন করে) তবে &&অপারেটর এখনও জানেন না a && bতাই এর ফলাফলটি bজানতে দৌড়াতে হবে। যদি bসফল হয় তবে a && bসফল হয় এবং ||জানে যে সামগ্রিক ফলাফল সাফল্য, তাই চালানোর দরকার নেই c। যদি bব্যর্থ হয়||এখনও অভিব্যক্তিটির মান জানে না, তাই চালানোর দরকার নেই c


7

অপারেটর && পরবর্তী কমান্ডটি কার্যকর করে যদি পূর্ববর্তী কমান্ডটির সফল প্রয়োগ হয়, (প্রস্থান প্রস্থান কোড ($?) 0 = যৌক্তিক সত্য)।

আকারে A && B || Cকমান্ড (অথবা শর্ত) একটি মূল্যায়ন করা হয় এবং যদি একজন ফেরৎ সত্য (বিজয়, প্রস্থান কোড 0) তারপর কমান্ড বি মৃত্যুদন্ড কার্যকর করা হয়। যদি একটি ব্যর্থ হয় (এভাবে মিথ্যা প্রত্যাবর্তন হবে - 0 ব্যতীত প্রস্থান কোড) এবং / বা বি ব্যর্থ হয় ( মিথ্যা প্রত্যাবর্তন ) তবে সি আদেশটি কার্যকর করা হবে।

এছাড়াও &&অপারেটরটি শর্ত চেকগুলিতে একটি AND হিসাবে ব্যবহৃত হয় এবং অপারেটর শর্ত পরীক্ষায় ওআর এর ||মতো কাজ করে ।

আপনার স্ক্রিপ্টের সাথে আপনি কী করতে চান তার উপর নির্ভর করে ফর্মটি A && B || Cআপনার উদাহরণের মতো শর্ত পরীক্ষার জন্য ব্যবহার করা যেতে পারে বা কমান্ডগুলি শৃঙ্খলাবদ্ধ করতে ব্যবহার করা যেতে পারে এবং যদি পূর্ববর্তী কমান্ডগুলির একটি সফল প্রস্থান কোড 0 থাকে তবে কমান্ডের একটি সিরিজ নিশ্চিত করা যায় ।
এই কেন এটা পছন্দ কমান্ড দেখতে খুবই সাধারণ হল:
do_something && do_something_else_that_depended_on_something

উদাহরণস্বরূপ:
apt-get update && apt-get upgrade যদি আপডেট ব্যর্থ হয় তবে আপগ্রেড কার্যকর করা হয় না, (বাস্তব বিশ্বে বোঝা যায় ...)।

mkdir test && echo "Something" > test/file
অংশটি সফল echo "Something"হলেই কার্যকর করা হবে mkdir testএবং অপারেশনটি প্রস্থান কোড 0 নম্বর দিয়েছিল ।

./configure --prefix=/usr && make && sudo make install
সাধারণত একসাথে প্রয়োজনীয় নির্ভরশীল কমান্ডগুলি চেইনে সংকলনের কাজগুলিতে পাওয়া যায়।

আপনি সঙ্গে "চেইন" উপরের বাস্তবায়ন চেষ্টা করুন যদি - তারপর - আর একটি সহজ কাজের জন্য - (ভুল হয়ে যেতে পারে আরো জিনিস এবং এইভাবে আরো কোড লিখতে) আপনি আরো অনেক কিছু কমান্ড এবং চেক করতে হবে।

এছাড়াও, && এবং || এর সাথে জড়িত আদেশগুলি মনে রাখবেন শেল থেকে বাম থেকে ডানে পড়া হয়। পূর্ববর্তী কয়েকটি কমান্ডের সফল আউটপুটটির পরবর্তী ধাপটি নির্ভর করতে আপনার ব্র্যাকেটগুলি সহ কমান্ড এবং কন্ডিশন চেকের গোষ্ঠীগুলির প্রয়োজন হতে পারে। উদাহরণস্বরূপ এটি দেখুন:

root@debian:$ true || true && false;echo $?
1 
#read from left to right
#true OR true=true AND false = false = exit code 1=not success

root@debian:$ true || (true && false);echo $?
0 
# true OR (true AND false)=true OR false = true = exit code 0 = success

বা বাস্তব জীবনের উদাহরণ:

root@debian:$ a=1;b=1;c=1;[[ $a -eq 1 ]] || [[ $b -eq 1 ]] && [[ $c -eq 2 ]];echo $?
1 
#condition $a = true OR condition b = true AND condition $c = false
#=> yields false as read from left to right, thus exit code=1 = not ok

root@debian:$ a=1;b=1;c=1;[[ $a -eq 1 ]] || [[ $b -eq 1 && $c -eq 2 ]];echo $?
0 
#vars b and c are checked in a group which returns false, 
#condition check of var a returns true, thus true OR false yields true = exit code 0

মনে রাখবেন যে কয়েকটি কমান্ডগুলি কার্যকর হওয়া প্রক্রিয়ার উপর নির্ভর করে বিভিন্ন প্রস্থান কোডগুলি ফেরত দেয় বা তাদের ক্রিয়ের উপর নির্ভর করে বিভিন্ন কোড ফেরত দেয় (উদাহরণস্বরূপ diff, জিএনইউ কমান্ড , দুটি ফাইল পৃথক হলে 1 প্রদান করে এবং যদি তারা না দেয় তবে 0 দেয় )। এই জাতীয় আদেশগুলি && এবং || তে যত্ন সহকারে চিকিত্সা করা দরকার ।

এছাড়াও কেবল সমস্ত ধাঁধা একসাথে রাখতে ;অপারেটর ব্যবহার করে কমান্ডের সংমিশ্রণটি মনে করুন । একটি বিন্যাসে সঙ্গে A;B;Cসব কমান্ড কোন ব্যাপার কি কমান্ডের প্রস্থান কোড ছিল সিরিজে মৃত্যুদন্ড কার্যকর করা হবে Aএবং B


1

বাশ ডকুমেন্টেশনের কারণে এআরএ্যান্ড ও ওআর তালিকা কল করার কারণে এটি সম্পর্কে বেশিরভাগ বিভ্রান্তি হতে পারে । যদিও কথাটি অনুরূপ &&এবং ||বর্গাকার বন্ধনীর ভিতরে পাওয়া যায় নি, তারা ভিন্নভাবে কাজ করে।

কিছু উদাহরণ এটি সেরা বর্ণনা করতে পারে ...

দ্রষ্টব্য: একক এবং ডাবল বর্গাকার বন্ধনী ( [ ... ]এবং [[ ... ]]) তাদের নিজস্ব কমান্ড যা তুলনা করে এবং একটি প্রস্থান কোড ফেরত দেয়। তাদের আসলে দরকার নেই if

cmda  && cmdb  || cmdc

যদি cmdaসত্য থেকে প্রস্থান হয়, cmdbকার্যকর করা হয়।
যদি cmdaমিথ্যা থেকে প্রস্থান cmdbহয়, কার্যকর হয় না তবে cmdcহয় but

cmda; cmdb  && cmdc  || cmdd

কীভাবে cmdaপ্রস্থান করা যায় তা উপেক্ষা করা হয়।
যদি cmdbসত্য থেকে প্রস্থান হয়, cmdcকার্যকর করা হয়।
যদি cmdbমিথ্যা থেকে প্রস্থান করে, cmdcকার্যকর হয় না এবং cmddহয়।

cmda  && cmdb; cmdc

যদি cmdaসত্য থেকে প্রস্থান cmdbহয়, কার্যকর হয় এবং তারপরে অনুসরণ করা হয় cmdc
যদি cmdaমিথ্যা থেকে প্রস্থান করে, cmdbমৃত্যুদন্ড কার্যকর করা হয় না তবে cmdcহয়।

তাই না? cmdcমৃত্যুদণ্ড কার্যকর করা হয় কেন ?
কারণ ব্যাখ্যাকারীর কাছে, একটি সেমিকোলন ( ;) এবং একটি নতুন লাইন হুবহু একই জিনিস বোঝায়। বাশ কোডের এই রেখাটিকে দেখছে ...

cmda  && cmdb
cmdc  

যা প্রত্যাশা করা হয় তা অর্জন cmdb; cmdcকরার জন্য, তাদের অবশ্যই একটি যৌগিক কমান্ড (গ্রুপ কমান্ড) করার জন্য আমাদের অবশ্যই কোঁকড়া ধনুর্বন্ধনী আবদ্ধ করতে হবে । অতিরিক্ত টার্মিনেটিং সেমিকোলন { ...; }সিনট্যাক্সের প্রয়োজন মাত্র । সুতরাং আমরা পেয়েছি ...

cmda && { cmdb; cmdc; }
যদি cmdaসত্য থেকে প্রস্থান cmdbহয়, কার্যকর হয় এবং তারপরে অনুসরণ করা হয় cmdc
যদি cmdaপ্রস্থানের মিথ্যা, তন্ন তন্ন cmdbবা cmdcমৃত্যুদন্ড কার্যকর করা হয়।
পরের লাইনে ফাঁসি কার্যকর হয়।

ব্যবহার

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

এখানে কিছু চলমান কোডের একটি উদাহরণ ...

fnInit () {
  :
  _fn="$1"
  ### fnInit "${FUNCNAME}" ...
  ### first argument MUST be name of the calling function
  #
  [[ "$2" == "--help-all" ]]  && { helpAll                      ; return 0; }
  ### pick from list of functions
  #
  [[ "$2" == "--note-all" ]]  && { noteAll                      ; return 0; }
  ### pick from notes in METAFILE
  #
  [[ "$2" == "--version"  ]]  && { versionShow "${_fn}" "${@:3}"; return 0; }
  #
  [[ "$2" == "--function" ]]  && {
    isFnLoaded "$3"           && { "${@:3}"                     ; return 0; }
    #
    errorShow functionnotfound "Unknown function:  $3"
    return 0
  }
  ### call any loaded function
  #
  [[ "$2" == "--help" || "$2" == "-h" ]]  && { noteShow "$_fn" "${@:3}"; return 0; }
  ### fnInit "${FUNCNAME}" --help or -h
  #
  return 1
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.