উদ্ধৃতিবিহীন ফাঁকা জায়গাগুলির সাথে প্যারামিটার বিস্তৃতি কেন ডাবল বন্ধনী "[[" কিন্তু একক বন্ধনী "[" "এর ভিতরে নয়?"


85

আমি একক বা ডাবল বন্ধনী ব্যবহার করে বিভ্রান্ত হয়েছি। এই কোডটি দেখুন:

dir="/home/mazimi/VirtualBox VMs"

if [[ -d ${dir} ]]; then
    echo "yep"
fi

স্ট্রিংয়ের একটি স্পেস থাকলেও এটি পুরোপুরি কাজ করে। তবে আমি যখন এটি একক বন্ধনীতে পরিবর্তন করি:

dir="/home/mazimi/VirtualBox VMs"

if [ -d ${dir} ]; then
    echo "yep"
fi

এটা বলে:

./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected

আমি যখন এটিকে পরিবর্তন করি:

dir="/home/mazimi/VirtualBox VMs"

if [ -d "${dir}" ]; then
    echo "yep"
fi

এটা ভাল কাজ করে। কি ঘটছে তা কেউ ব্যাখ্যা করতে পারেন? "${var}"স্পেস দ্বারা সৃষ্ট সমস্যাগুলি প্রতিরোধ করতে আমার যখন ভেরিয়েবলগুলির চারপাশে ডাবল কোটস অর্পণ করা উচিত ?



আরও জেনেরিক বনাম প্রশ্ন: unix.stackexchange.com
সিরো সান্তিলি 新疆 改造 中心 法轮功 六四 事件

উত্তর:


83

একক বন্ধনী [হ'ল testকমান্ডের জন্য একটি নাম , এটি সিনট্যাক্স নয়

একক বন্ধনীটির একটি ডাউনসাইড (অনেকের) মধ্যে একটি হ'ল যদি এক বা একাধিক অপারেশন যদি খালি স্ট্রিংটি ফেরতের মূল্যায়ন করার চেষ্টা করে তবে এটি অভিযোগ করবে যে এটি দুটি অপারেন্ড (বাইনারি) প্রত্যাশা করেছিল। এই কারণেই আপনি লোকজনকে দেখেন [ x$foo = x$blah ], xগ্যারান্টি দেয় যে অপারেন্ড কখনই খালি স্ট্রিংকে মূল্যায়ন করবে না।

[[ ]]অন্যদিকে ডাবল বন্ধনী সিনট্যাক্স এবং এর চেয়ে অনেক বেশি সক্ষম [ ]। আপনি যেমনটি খুঁজে পেয়েছেন, এতে একক অপারেন্ড সমস্যা নেই এবং এটি >, <, >=, <=, !=, ==, &&, ||অপারেটরগুলির সাথে আরও সি-জাতীয় সিনট্যাক্সের অনুমতি দেয় ।

আমার প্রস্তাবনাটি নিম্নলিখিত: আপনার যদি দোভাষী হয় #!/bin/bashতবে সর্বদা ব্যবহার করুন[[ ]]

এটি লক্ষ্য করা গুরুত্বপূর্ণ যে [[ ]]সমস্ত পসিক্স শেলগুলি সমর্থন করে না, তবে অনেকগুলি শেল এটি সমর্থন করে যেমন zshএবং kshপাশাপাশিbash


16
উদ্ধৃতি ব্যবহার করে খালি স্ট্রিং (এবং অন্যান্য অনেকগুলি) সমস্যা সমাধান করা হয়। "এক্স" হ'ল অন্য ধরণের সমস্যা cover াকতে : যেখানে অপারেটরগুলি অপারেটর হিসাবে নেওয়া যেতে পারে । ভালো লেগেছে যখন $fooহয় !বা (বা -n... যে সমস্যা POSIX শাঁস সঙ্গে একটি সমস্যা যেখানে আর্গুমেন্ট নম্বর (পাশে হতে বোঝানো হয় না [এবং ]) হল চার থেকে বড় নয়।
স্টাফেন চেজেলাস 25'13

21
স্পষ্ট করা, [ x$foo = x$blah ]ঠিক যেমন স্পষ্ট ভুল [ $foo = $bar ][ "$foo" = "$bar" ]যে কোনও পসিএক্স অনুগত শেলটি সঠিক, [ "x$foo" = "x$bar" ]কোনও বোর্নের মতো শেলটিতে এটি কাজ করবে তবে এটি xএমন ক্ষেত্রে নয় যেখানে আপনার খালি স্ট্রিং রয়েছে তবে যেখানে $fooহতে পারে !বা -n...
স্টাফেন চেজেলাস

1
এই উত্তরে আকর্ষণীয় শব্দার্থক। আমি নিশ্চিত না যে আপনি এটি * সিনট্যাক্স নয় বলে কী বোঝাতে চাইছেন । অবশ্যই, [এটির জন্য নির্দিষ্টভাবে কোনও উপনাম নয় test। যদি এটি হয় তবে testক্লোজিং স্কোয়ার ব্র্যাকেটটি গ্রহণ করবে। test -n foo ]। কিন্তু testনা, এবং একটি [প্রয়োজন। অন্যান্য সমস্ত ক্ষেত্রে [অভিন্ন test, তবে এটি কীভাবে aliasকাজ করে তা নয় । ব্যাশ বর্ণনা [এবং testযেমন শেল builtins কিন্তু [[হিসেবে শেল শব্দ
কোজিরো

1
ঠিক আছে, বাশে [একটি শেল বিল্টিন রয়েছে তবে / usr / bin / [এছাড়াও একটি এক্সিকিউটেবল। এটি usতিহ্যগতভাবে / usr / bin / পরীক্ষার একটি লিঙ্ক, তবে আধুনিক gnu কোরুটিলেস পৃথক বাইনারি। পরীক্ষার traditionalতিহ্যবাহী সংস্করণটি আরগভি [0] পরীক্ষা করে এটি দেখতে [এবং তারপরে মিলের সন্ধান করে] তা পরীক্ষা করে দেখুন।
ইভান

আমার বাশ এর সাথে কাজ করে না >=এবং<=
ছাত্র

51

[কমান্ড একজন সাধারণ কমান্ড। যদিও বেশিরভাগ শেলগুলি এটিকে দক্ষতার জন্য অন্তর্নির্মিত হিসাবে সরবরাহ করে, এটি শেলের সাধারণ সিনট্যাকটিক নিয়ম মানায়। [একেবারে সমতুল্য test, ব্যতীত এটির শেষ যুক্তি হিসাবে [একটি প্রয়োজন ]এবং testএটি নাও করে।

ডাবল বন্ধনী [[ … ]]বিশেষ বাক্য গঠন। এগুলি কেএসএতে প্রবর্তিত হয়েছিল (বেশ কয়েক বছর পরে [) কারণ [সঠিকভাবে ব্যবহার করতে সমস্যা হতে পারে এবং [[শেল বিশেষ অক্ষর ব্যবহার করে এমন কিছু নতুন সুন্দর সংযোজন মঞ্জুরি দেয়। উদাহরণস্বরূপ, আপনি লিখতে পারেন

[[ $x = foo && $y = bar ]]

কারণ সমগ্র শর্তাধীন অভিব্যক্তি শেল দ্বারা পার্স করা হয়, যেহেতু [ $x = foo && $y = bar ]প্রথম দুই কমান্ড বিভক্ত করা হবে [ $x = fooএবং $y = bar ]দ্বারা পৃথক &&অপারেটর। একইভাবে ডাবল বন্ধনী প্যাটার্ন মেলানো সিনট্যাক্সের মতো জিনিসগুলিকে সক্ষম করে, উদাহরণস্বরূপ, [[ $x == a* ]]মানটির xশুরু হয় কিনা তা পরীক্ষা করা a; একক বন্ধনীতে এটি a*ফাইলের তালিকায় প্রসারিত হবে যার নাম aবর্তমান ডিরেক্টরিতে শুরু হয় । ডাবল বন্ধনী প্রথমে ksh এ প্রবর্তিত হয়েছিল এবং কেবল ksh, bash এবং zsh এ উপলব্ধ।

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

[[ $var1 = "$var2" ]]আপনি যদি বাইট-টু-বাইট স্ট্রিং তুলনা করতে চান তবে আপনার ব্যতিক্রমগুলি এখানে ব্যতিক্রম , অন্যথায়, এর বিপরীতে $var2মেলে একটি প্যাটার্ন be$var1

একটি জিনিস যা আপনি করতে পারবেন না তা [[ … ]]হ'ল অপারেটর হিসাবে ভেরিয়েবল ব্যবহার। উদাহরণস্বরূপ, এটি পুরোপুরি আইনী (তবে খুব কমই কার্যকর):

if [ -n "$reverse_sort" ]; then op=-gt; else op=-lt; fi

if [ "$x" "$op" "$y" ]; then 

আপনার উদাহরণে

dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then 

ভিতরে কমান্ড ifহল [4 আর্গুমেন্ট সহ -d, /home/mazimi/VirtualBox, VMsএবং ]। শেলটি পার্স করে -d /home/mazimi/VirtualBoxএবং তারপরে কী করতে হবে তা জানে না VMs${dir}একটি সুসংগঠিত কমান্ড পেতে আপনার শব্দ বিভাজন রোধ করা উচিত ।

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

  • একটি অ্যাসাইনমেন্টে: foo=$bar(তবে নোট করুন যে আপনার export "foo=$bar"যেমন বা অ্যারে অ্যাসাইনমেন্টে ডাবল উক্তি প্রয়োজন array=("$a" "$b"));
  • একটি caseবিবৃতিতে case $foo in …:;
  • এর ডান দিকে ব্যতীত ডবল বন্ধনী ভিতরে =বা ==: অপারেটর (যতক্ষণ না আপনি প্যাটার্ন ম্যাচিং চাও) [[ $x = "$y" ]]

এই সমস্ত ক্ষেত্রে ডাবল উক্তি ব্যবহার করা সঠিক, সুতরাং আপনি উন্নত নিয়মগুলি এড়িয়ে যেতে এবং সর্বদা উদ্ধৃতি ব্যবহার করতে পারেন।


1
পছন্দ করুন এটি [প্রকৃতপক্ষে 1981 সালে সিস্টেম তৃতীয় থেকে এসেছে , আমি ভেবেছিলাম এটি আরও পুরানো।
গিলস

8

"${var}"স্পেস দ্বারা সৃষ্ট সমস্যাগুলি প্রতিরোধ করতে আমার যখন ভেরিয়েবলগুলির চারপাশে ডাবল কোটস অর্পণ করা উচিত ?

এই প্রশ্নের অন্তর্নিহিত হয়

কেন যথেষ্ট ভাল না?${variable_name}

${variable_name} এর অর্থ এই নয় যে আপনি কী ভাবেন এটি করে ...

... যদি তুমি এটা আছে মনে কিছু শূণ্যস্থান দ্বারা সৃষ্ট সমস্যার সঙ্গে কি (পরিবর্তনশীল মান)। এটির জন্য ভাল:${variable_name}

$ bar=foo
$ bard=Shakespeare
$ echo $bard
Shakespeare
$ echo ${bar}d
food

এবং আর কিছুনা! 1  তাত্ক্ষণিকভাবে এমন একটি চরিত্রের সাথে অনুসরণ করে যা ভেরিয়েবল নামের অংশ হতে পারে: 1 কোনও ভালকরে না: চিঠি (-বা-), একটি আন্ডারস্কোর () বা একটি অঙ্ক (-)। এবং তারপরেও আপনি এটিকে ঘিরে কাজ করতে পারেন:${variable_name}AZaz_09

$ echo "$bar"d
food

আমি এর ব্যবহারকে নিরুৎসাহিত করার চেষ্টা করছি না - echo "${bar}d"সম্ভবত এটিই এখানে সেরা সমাধান - তবে লোকদের উদ্ধৃতিগুলির পরিবর্তে ব্রেসগুলির উপর নির্ভর করা বা সহজাত ব্রেস প্রয়োগ করা এবং তারপরে জিজ্ঞাসা করা, "এখন, আমারও উদ্ধৃতিও দরকার ? ”  আপনার কাছে সর্বদা উদ্ধৃতি ব্যবহার করা উচিত যদি না আপনার কাছে কারণ না থাকে এবং আপনি নিশ্চিত যে আপনি কী করছেন তা আপনি নিশ্চিত।
_________________
1    অবশ্যই, প্যারামিটার সম্প্রসারণের অনুরাগী রূপগুলি উদাহরণস্বরূপ এবং সিনট্যাক্সের উপর ভিত্তি করে তৈরি করা উচিত । এছাড়াও, আপনি ব্যবহার করতে হবে , ইত্যাদি 10th, 11 ইত্যাদি অবস্থানগত পরামিতি রেফারেন্স - কোট যে আপনাকে সাহায্য করা হবে না।${parameter:-[word]}${parameter%[word]}${parameter}${10}${11}


2

স্থানগুলি এবং ফাঁকা | ভ্যারিয়েবলের বিশেষ অক্ষরগুলি পরিচালনা করার জন্য আপনাকে এগুলি সর্বদা ডাবল কোট দিয়ে ঘিরে রাখা উচিত। সঠিক আইএফএস স্থাপন করাও একটি ভাল অনুশীলন।

প্রস্তাবিত: http://www.dwheeler.com/essays/filenames-in-shell.html

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.