একাধিক শর্ত সাবশেল না থাকলে বাশ?


23

আমি বিবৃতি থাকলে শেলের মধ্যে একাধিক শর্ত একত্রিত করতে চাই এবং সংমিশ্রণটি অস্বীকার করব। শর্তগুলির একটি সহজ সংমিশ্রণের জন্য আমার কাছে নিম্নলিখিত কার্য কোডটি রয়েছে:

if [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ; then
  # do stuff with the files
fi

এটি কাজ করে। যদি আমি এটিকে অবহেলা করতে চাই তবে আমি নিম্নলিখিত কার্য কোডটি ব্যবহার করতে পারি:

if ! ( [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ) ; then
  echo "Error: You done goofed."
  exit 1
fi
# do stuff with the files

এটিও প্রত্যাশার মতো কাজ করে। যাইহোক, এটি আমার কাছে ঘটে যে আমি প্রথম বন্ধনীগুলি সেখানে কী করছে তা আমি জানি না। আমি সেগুলি কেবল গোষ্ঠীকরণের জন্য ব্যবহার করতে চাই , তবে এটি কি আসলে একটি সাবশেল তৈরি করছে? (আমি কীভাবে বলতে পারি?) যদি তা হয় তবে সাবস্কেল তৈরি না করে শর্তগুলি গোছানোর কোনও উপায় আছে কি?


আমি মনে করি সমান অভিব্যক্তিটি নির্ধারণ করতে আমি বুলিয়ান যুক্তিও ব্যবহার করতে পারি: if ! [ -f file1 ] || ! [ -f file 2 ] || ! [ -f file3 ] ; thenতবে আমি আরও সাধারণ উত্তর চাই।
ওয়াইল্ডকার্ড

আপনি ধনুর্বন্ধনীগুলির অভ্যন্তরে if [[ ! -f file1 ]] && [[ ! -f file2 ]]; then
অবহেলা

1
হ্যাঁ, আমি কেবল পরীক্ষা করেছি if [ ! 1 -eq 2 ] && [ ! 2 -eq 3 ]; then echo yep; fiএবং এটি কার্যকর। আমি সবসময় অভ্যাসের বিষয় হিসাবে ডাবল-ব্রেস দিয়ে পরীক্ষা লিখি। এছাড়াও, এটি নিশ্চিত না করার জন্য bash, আমি আরও পরীক্ষা করেছি if /bin/test ! 1 -eq 2 && /bin/test ! 2 -eq 3 ; then echo yep; fiএবং এটি সেভাবে কাজ করে।
ডোপঘোতি

1
@ উইল্ডকার্ড - [ ! -e file/. ] && [ -r file ]ডিরেক্টরি বাদ দেবে। আপনার পছন্দ মত এটিকে অবহেলা করুন। অবশ্যই, এটি কি -dকরে।
মাইক্রজারভ 21

1
সম্পর্কিত প্রশ্ন (অনুরূপ তবে তেমন আলোচনা এবং উত্তরগুলি তেমন সহায়ক নয়): unix.stackexchange.com/q/156885/135943
ওয়াইল্ডকার্ড

উত্তর:


32

এর { list;}পরিবর্তে আপনার প্রয়োজন (list):

if ! { [ -f file1 ] && [ -f file2 ] && [ -f file3 ]; }; then
  : do something
fi

উভয়ই গ্রুপিং কমান্ড , তবে { list;}বর্তমান শেল পরিবেশে কমান্ড কার্যকর করে।

উল্লেখ্য, ;{ list;}তালিকা থেকে সীমানা প্রয়োজন হয় }বিপরীত শব্দ, আপনি পাশাপাশি অন্যান্য বিভেদক ব্যবহার করতে পারেন। এর পরে স্থান (বা অন্যান্য সীমানা) {এছাড়াও প্রয়োজন।


ধন্যবাদ! এমন কিছু যা আমাকে প্রথমে ছড়িয়ে দিয়েছে (যেহেতু আমি কোঁকড়া ধনুর্বন্ধনী ব্যবহারের awkচেয়ে বেশি ক্ষেত্রে প্রায়শই ব্যবহার করি bash) হ'ল খোলা কোঁকড়ানো ধনুর্বন্ধনী পরে সাদা স্থান প্রয়োজন। আপনি উল্লেখ করেছেন "আপনি অন্যান্য সীমানা ব্যবহার করতে পারেন"; কোন উদাহরণ?
ওয়াইল্ডকার্ড

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

@ ডন_ক্রিসটি: ইন zsh, আপনি হোয়াইটস্পেস ব্যবহার করতে পারেন
কিউংলম

@ ডন_ক্রিসটি: &এটিও একটি বিভাজক, আপনি ব্যবহার করতে পারেন { echo 1;:&}, একাধিক নতুন লাইনও ব্যবহার করা যেতে পারে।
cuonglm

2
আপনি স্বনির্ধারিত থেকে কোন metacharacter উদ্ধৃতি ব্যবহার করতে পারেন they must be separated from list by whitespace or another shell metacharacter.ব্যাশ তারা হল: metacharacter: | & ; ( ) < > space tab । এই নির্দিষ্ট কাজের জন্য, আমি বিশ্বাস করি যে কোনও & ; ) space tabকাজ করবে। .... .... zsh থেকে (মন্তব্য হিসাবে) each sublist is terminated by &', &!', or a newline.

8

আপনি testযা চান তা অর্জন করতে আপনি পুরো কার্যকারিতাটি ব্যবহার করতে পারেন। ম্যান পেজ থেকে test:

 ! expression  True if expression is false.
 expression1 -a expression2
               True if both expression1 and expression2 are true.
 expression1 -o expression2
               True if either expression1 or expression2 are true.
 (expression)  True if expression is true.

সুতরাং আপনার অবস্থা দেখতে দেখতে পারে:

if [ -f file1 -a -f file2 -a -f file3 ] ; then
    # do stuff with the files
fi

অব্যাহত ব্যবহার বন্ধুত্ব অবহেলার জন্য:

if [ ! \( -f file1 -a -f file2 -a -f file3 \) ] ; then
    echo "Error: You done goofed."
    exit 1
fi
# do stuff with the files

6

করতে portably শেল মধ্যে একটি জটিল শর্তাধীন অস্বীকার, হয় আপনি আবেদন করতে হবে ডি মরগান আইন ভিতরে নিচে অস্বীকৃতি সব পথ ধাক্কা [কল ...

if [ ! -f file1 ] || [ ! -f file2 ] || [ ! -f file3 ]
then
    # do stuff
fi

... বা আপনার অবশ্যই ব্যবহার করা উচিত then :; else...

if [ -f file1 ] && [ -f file2 ] && [ -f file3 ]
then :
else
  # do stuff
fi

if ! commandবহনযোগ্যভাবে উপলব্ধ এবং না হয় [[

আপনার যদি মোট পোর্টেবিলিটিটির প্রয়োজন না হয় তবে শেল স্ক্রিপ্টটি লিখবেন না । আপনি আসলে করছি আরো এটি সম্ভবত /usr/bin/perlএকটি এলোমেলোভাবে নির্বাচিত ইউনিক্স এ আপনার চেয়ে bash


1
!পজিক্স যা আজকাল বহনযোগ্য পর্যাপ্ত। এমনকি বোর্ন শেলটি সহ যে জাহাজগুলি প্রেরণ করা হয় তাদেরও ফাইল সিস্টেমে অন্য কোথাও একটি পসিক্স থাকে যা আপনি আপনার স্ট্যান্ডার্ড সিনট্যাক্সটি ব্যাখ্যা করতে ব্যবহার করতে পারেন।
স্টাফেন চেজেলাস

@ StéphaneChazelas এটি প্রযুক্তিগতভাবে সত্য কিন্তু আমার অভিজ্ঞতা এটা পার্ল মধ্যে একটি স্ক্রিপ্ট পুনর্লিখন তুলনায় এটি লোকেটিং এবং POSIX-অনুবর্তী শেল পরিবেশ থেকে শুরু সক্রিয় করার অসুবিধা মোকাবেলা হয় সহজ /bin/sh। অটোকনফ স্ক্রিপ্টগুলি আপনার পরামর্শ অনুসারে করে তবে আমি মনে করি যে আমরা সকলেই জানি যে এটি কতটা কম অনুমোদন।
zwol

5

অন্যরা {যৌগিক কমান্ডের ;}গোষ্ঠীকরণের বিষয়টি লক্ষ্য করেছেন , তবে আপনি যদি সেটটিতে অভিন্ন পরীক্ষা করছেন তবে আপনি অন্যরকম ব্যবহার করতে পছন্দ করতে পারেন:

if  ! for f in file1 file2 file3
      do  [ -f "$f" ] || ! break
      done
then  : do stuff
fi

... অন্য কোথাও প্রদর্শিত হয়েছে { :;}, বাসা বাঁধার কম্যান্ডের সাথে কোনও অসুবিধা নেই ...

নোট করুন যে উপরের (সাধারণত) নিয়মিত ফাইলগুলির জন্য পরীক্ষা করা হয়। আপনি যদি কেবল বিদ্যমান , পঠনযোগ্য ফাইলগুলি সন্ধান করেন যা ডিরেক্টরি নয়:

if  ! for f in file1 file2 file3
      do  [ ! -d "$f" ] && 
          [   -r "$f" ] || ! break
      done
then  : do stuff
fi

তারা যদি ডিরেক্টরি না হয় তবে তা যদি আপনার যত্ন না নেয়:

if  ! command <file1 <file2 <file3
then  : do stuff
fi

... যে কোন পঠনযোগ্য , অ্যাক্সেসযোগ্য ফাইলের জন্য কাজ করে তবে সম্ভবত ফিফো ডাব্লু / আউট লেখকদের জন্য ঝুলবে।


2

এটি আপনার মূল প্রশ্নের সম্পূর্ণ উত্তর নয়, তবে আমি লক্ষ্য করেছি যে আপনি একটি মন্তব্যে যৌগিক পরীক্ষার (পঠনযোগ্য ফাইল) উল্লেখ করেছেন; যেমন,

if [ -f file1 ] && [ -r file1 ] && [ -f file2 ] && [ -r file2 ] && [ -f file3 ] && [ -r file3 ]

শেল ফাংশনটি সংজ্ঞায়িত করে আপনি এটিকে কিছুটা সংহত করতে পারেন; যেমন,

readable_file()
{
    [ -f "$1" ]  &&  [ -r "$1" ]
}

[ $# = 1 ]স্বাদে (যেমন, ) হ্যান্ডলিংয়ে ত্রুটি যুক্ত করুন । ifউপরের প্রথম বিবৃতিতে এখন কনডেন্স করা যায়

if readable_file file1  &&  readable_file file2  &&  readable_file file3

এবং আপনি ফাংশনটির নামটি ছোট করে এটিকে আরও ছোট করতে পারেন। তেমনি, আপনি সংজ্ঞায়িত করতে পারেন not_readable_file()(বা nrfসংক্ষিপ্ত জন্য) এবং ফাংশন মধ্যে অবহেলা অন্তর্ভুক্ত।


ভাল লাগল, তবে কেন শুধু একটি লুপ যুক্ত করবেন না? readable_files() { [ $# -eq 0 ] && return 1 ; for file in "$@" ; do [ -f "$file" ] && [ -r "$file" ] || return 1 ; done ; } (অস্বীকৃতি: আমি এই কোডটি পরীক্ষা করেছি এবং এটি কাজ করে তবে এটি কোনও ওয়ান-লাইনার ছিল না I আমি এখানে পোস্ট করার জন্য সেমিকোলন যুক্ত করেছি তবে তাদের অবস্থান নির্ধারণের পরীক্ষা নিই না))
ওয়াইল্ডকার্ড

1
ভাল যুক্তি. আমি সামান্য উদ্বেগ উত্থাপন করব যে এটি ফাংশনে নিয়ন্ত্রণ (সংযোগ) যুক্তি আরও লুকিয়ে রাখে; স্ক্রিপ্টটি পড়ে এবং দেখে if readable_files file1 file2 file3এমন কেউ জানতে পারে না যে ফাংশনটি AND বা OR করছে কিনা - যদিও (ক) আমার ধারণা এটি মোটামুটি স্বজ্ঞাত, (খ) আপনি যদি স্ক্রিপ্টটি বিতরণ না করে থাকেন তবে আপনি যদি এটি বুঝতে পারেন তবে যথেষ্ট it's এবং (গ) যেহেতু আমি ফাংশনটির নামটিকে অস্পষ্ট করে সংক্ষিপ্তকরণের পরামর্শ দিয়েছি, আমি পঠনযোগ্যতার বিষয়ে কথা বলার মতো অবস্থানে নেই। … (করণীয়)
জি-ম্যান

1
(চালিয়ে যাওয়া) ... বিটিডাব্লু, আপনি যেভাবে লিখেছেন সেটি ফাংশনটি ঠিকঠাক, তবে আপনি এটির for file in "$@" ; doসাথে প্রতিস্থাপন করতে পারেন for file do- এটি ডিফল্ট হয় in "$@"এবং (কিছুটা স্বতঃস্ফূর্তভাবে) ;কেবল অপ্রয়োজনীয়ই নয় তবে প্রকৃতপক্ষে নিরুৎসাহিত হয়।
জি-ম্যান বলছেন 'মনিকা পুনরায় ইনস্টল করুন'

0

আপনি ব্রেস পরীক্ষাগুলির ভিতরেও প্রত্যাখ্যান করতে পারেন, তাই আপনার মূল কোডটি পুনরায় ব্যবহার করতে:

if [[ ! -f file1 ]] || [[ ! -f file2 ]] || [[ ! -f file3 ]] ; then
  # do stuff with the files
fi

2
||পরিবর্তে আপনার প্রয়োজন&&
cuonglm

পরীক্ষা নয় "হয় কোন সেখানে নেই ফাইলের", পরীক্ষা হল "হয় কেউ ফাইল সেখানে"। ব্যবহার ||সম্পৃক্ত চালানো তাহলে কোন ফাইল উপস্থিত না, না যদি এবং কেবল iff সব ফাইল উপস্থিত না। নট (এ এবং বি এবং সি) হ'ল (না এ) এবং (না বি) এবং (নট সি); আসল প্রশ্নটি দেখুন
ডোপঘোতি

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

2
@ ডোপগোতি: not (a and b)এর মতোই (not a) or (not b)। দেখুন en.wikipedia.org/wiki/De_Morgan%27s_laws
cuonglm

1
এটি বৃহস্পতিবার হতে হবে। আমি কখনই বৃহস্পতিবারের হ্যাং পেতে পারি না। সংশোধন করা হয়েছে, এবং আমি উত্তরসূরির জন্য আমার পাদদেশে মুখ ছেড়ে দেব।
ডোপঘোতি

-1

আমি সেগুলি কেবল গোষ্ঠীকরণের জন্য ব্যবহার করতে চাই, তবে এটি কি আসলে একটি সাবশেল তৈরি করছে? (আমি কীভাবে বলতে পারি?)

হ্যাঁ, এর মধ্যে থাকা কমান্ডগুলি (...)একটি সাব-শেইলে চালিত হয়।

আপনি কোনও সাব-শেলের মধ্যে আছেন কিনা তা পরীক্ষা করতে আপনি আপনার বর্তমান শেলের পিআইডিকে ইন্টারেক্টিভ শেলের পিআইডি সাথে তুলনা করতে পারেন।

echo $BASHPID; (echo $BASHPID); 

আউটপুট উদাহরণস্বরূপ, দেখানো হচ্ছে যে প্রথম বন্ধনীগুলি একটি সাবশেল বানায় এবং কোঁকড়া ধনুর্বন্ধনী হয় না:

$ echo $BASHPID; (echo $BASHPID); { echo $BASHPID;}
50827
50843
50827
$ 

6
()স্প্যান সাবশেল করে {}... যা
ঘটেছিল

@ হাইমাইল, এটিই আমার প্রশ্নের অন্য অংশ there এমন কিছু উপায় আছে যা আমি আমার স্ক্রিনে দেখতে বা প্রদর্শন করতে পারি যে একটি সাবসেল তৈরি হওয়ার সত্যতা রয়েছে? (এটি সত্যিই আলাদা প্রশ্ন হতে পারে তবে এখানে জেনে রাখা ভাল))
ওয়াইল্ডকার্ড

1
আপনি ঠিক বলেছেন! আমি echo $$ && ( echo $$ )পিআইডি'র তুলনা করার চেষ্টা করেছি এবং সেগুলি একই ছিল তবে আমি আপনাকে মন্তব্যটি ভুল করে ভুল জমা দেওয়ার আগে আমি অন্য একটি জিনিস চেষ্টা করেছিলাম। echo $BASHPID && ( echo $BASHPID )বিভিন্ন পিআইডি দেয়
ডেভিড কিং

1
@ হেইমাইল echo $BASHPID && { echo $BASHPID; }আপনার অনুরোধ অনুসারে একই পিআইডি দেবে the শিক্ষার জন্য ধন্যবাদ
ডেভিড কিং

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