কেউ আমাকে শেল স্ক্রিপ্টে ভেরিয়েবলের চারপাশে উদ্ধৃতিগুলি আবদ্ধ করা উচিত কিনা তা বলতে পারেন?
উদাহরণস্বরূপ, নিম্নলিখিতটি সঠিক:
xdg-open $URL
[ $? -eq 2 ]
অথবা
xdg-open "$URL"
[ "$?" -eq "2" ]
আর যদি তাই হয় তবে কেন?
কেউ আমাকে শেল স্ক্রিপ্টে ভেরিয়েবলের চারপাশে উদ্ধৃতিগুলি আবদ্ধ করা উচিত কিনা তা বলতে পারেন?
উদাহরণস্বরূপ, নিম্নলিখিতটি সঠিক:
xdg-open $URL
[ $? -eq 2 ]
অথবা
xdg-open "$URL"
[ "$?" -eq "2" ]
আর যদি তাই হয় তবে কেন?
উত্তর:
সাধারণ নিয়ম: যদি তা ফাঁকা থাকে বা ফাঁকা স্থান (বা সত্যই কোনও সাদা জায়গা) বা বিশেষ অক্ষর (ওয়াইল্ডকার্ড) থাকতে পারে তবে এটিকে উদ্ধৃত করুন। ফাঁকা জায়গাগুলির সাথে স্ট্রিং উদ্ধৃতি না দেওয়ার ফলে প্রায়শই শেল অনেকের মধ্যে একক যুক্তিকে বিচ্ছিন্ন করে তোলে।
$?
এটি একটি সংখ্যাসূচক মান হওয়ায় উদ্ধৃতিগুলির দরকার নেই। কিনা $URL
এটা কি আপনি সেখানে অনুমতি উপর নির্ভর করে এবং আপনি এখনও একটি আর্গুমেন্ট চান কিনা এটা খালি যদি প্রয়োজন।
আমি সর্বদা অভ্যাসের বাইরে স্ট্রিংগুলি উদ্ধৃত করি যেহেতু এটি সেভাবেই নিরাপদ।
IFS=0
, তবে echo $?
খুব অবাক হতে পারে।
cp $source1 $source2 $dest
, তবে যদি কিছু অপ্রত্যাশিত কারণে dest
সেট না হয়ে যায় তবে তৃতীয় যুক্তিটি কেবল অদৃশ্য হয়ে যায় এবং এটি আপনাকে দেওয়ার পরিবর্তে নিঃশব্দে অনুলিপি source1
করে দেবে source2
ফাঁকা গন্তব্যের জন্য যথাযথ ত্রুটি (যেমনটি যদি আপনি প্রতিটি যুক্তির উদ্ধৃতি দিয়ে থাকেন)।
quote it if...
চিন্তার প্রক্রিয়াটি পিছনের দিকে রয়েছে - কোটগুলি আপনার যখন প্রয়োজন হয় তখন যুক্ত হয় না, এগুলি এমন কিছু যা আপনার যখন প্রয়োজন হয় তখন মুছে ফেলা হয়। ডাবল উদ্ধৃতি ব্যবহার করার প্রয়োজন না হলে (যেমন ভেরিয়েবলটি প্রসারিত করতে) বা কোনও উদ্ধৃতি ব্যবহার করার প্রয়োজন না হয় (যেমন গ্লোব্বিং এবং ফাইলের নাম সম্প্রসারণ) to
সংক্ষেপে, যেখানে টোকেন বিভক্তকরণ এবং ওয়াইল্ডকার্ড সম্প্রসারণের জন্য আপনার শেলের প্রয়োজন নেই সেখানে সবকিছু উদ্ধৃত করুন।
একক উদ্ধৃতি তাদের মধ্যবর্তী শব্দটিকে ভারব্যাটিক রক্ষা করে। শেলটি স্ট্রিংটি একেবারেই স্পর্শ না করে তা নিশ্চিত করার দরকার হলে এটি যথাযথ সরঞ্জাম। সাধারণত যখন আপনার ভেরিয়েবল ইন্টারপোলেশন প্রয়োজন হয় না তখন এটি পছন্দের উদ্ধৃতি প্রক্রিয়া।
$ echo 'Nothing \t in here $will change'
Nothing \t in here $will change
$ grep -F '@&$*!!' file /dev/null
file:I can't get this @&$*!! quoting right.
ভেরিয়েবল ইন্টারপোলেশন প্রয়োজন হলে ডাবল উদ্ধৃতিগুলি উপযুক্ত। উপযুক্ত অভিযোজন সহ, যখন আপনার স্ট্রিংয়ে একক উদ্ধৃতি দরকার হয় তবে এটি ভাল কাজ। (একক উদ্ধৃতিগুলির মধ্যে একক উদ্ধৃতি থেকে বাঁচার কোনও সহজ উপায় নেই, কারণ একক উদ্ধৃতিগুলির মধ্যে কোনও পলায়নের ব্যবস্থা নেই - যদি সেখানে থাকে তবে তারা সম্পূর্ণরূপে ভারব্যাটিকাম উদ্ধৃত করে না।)
$ echo "There is no place like '$HOME'"
There is no place like '/home/me'
টোকেন বিভক্তকরণ এবং / অথবা ওয়াইল্ডকার্ড সম্প্রসারণ করার জন্য যখন শেলটি বিশেষত আপনার প্রয়োজন হয় তখন কোনও উদ্ধৃতি উপযুক্ত নয়।
টোকেন বিভাজন;
$ words="foo bar baz"
$ for word in $words; do
> echo "$word"
> done
foo
bar
baz
বিপরীতে:
$ for word in "$words"; do echo "$word"; done
foo bar baz
(লুপটি কেবল একবারে, একক, উদ্ধৃত স্ট্রিংয়ের উপরে চলে)
$ for word in '$words'; do echo "$word"; done
$words
(লুপটি কেবল একবারে আক্ষরিক একক-উদ্ধৃত স্ট্রিংয়ের উপরে চলে)
ওয়াইল্ডকার্ড সম্প্রসারণ:
$ pattern='file*.txt'
$ ls $pattern
file1.txt file_other.txt
বিপরীতে:
$ ls "$pattern"
ls: cannot access file*.txt: No such file or directory
(আক্ষরিক নামে কোনও ফাইল নেই file*.txt
))
$ ls '$pattern'
ls: cannot access $pattern: No such file or directory
(কোনও ফাইলের নাম নেই $pattern
, হয়!)
আরও কংক্রিটের শর্তে, কোনও ফাইলের নাম সম্বলিত যে কোনও কিছুই সাধারণত উদ্ধৃত করা উচিত (কারণ ফাইলের নামগুলিতে হোয়াইটস্পেস এবং অন্যান্য শেল মেটাচার্যাকার থাকতে পারে)। ইউআরএলযুক্ত যে কোনও কিছু সাধারণত উদ্ধৃত করা উচিত (কারণ অনেকগুলিতে ইউআরএলগুলিতে শেল মেটাচার্যাক্টর থাকে ?
এবং &
)। একটি রেজেক্সযুক্ত যে কোনও কিছু সাধারণত উদ্ধৃত করা উচিত (ডাইটো ডাইটো)। অ-হোয়াইটস্পেস অক্ষরের মধ্যে একক স্পেস ব্যতীত উল্লেখযোগ্য শ্বেতস্পেসের যে কোনও কিছু উদ্ধৃত করা দরকার (কারণ অন্যথায় শেলটি সাদা স্থানটিকে কার্যকরভাবে একক স্পেসে স্থানান্তরিত করে এবং কোনও নেতৃস্থানীয় বা পেছনের শ্বেত স্পেস ছাঁটাই করবে)।
যখন আপনি জানেন যে কোনও ভেরিয়েবলের মধ্যে কেবল এমন কোনও মান থাকতে পারে যা কোনও শেল মেটাচার্যাক্টর ধারণ করে না, উদ্ধৃতিটি optionচ্ছিক। সুতরাং, একটি অনাকাক্সিক্ষত $?
মূলত ভাল, কারণ এই ভেরিয়েবলটি কেবলমাত্র একটি সংখ্যক থাকতে পারে। তবে "$?"
এটিও সঠিক, এবং সাধারণ ধারাবাহিকতা এবং নির্ভুলতার জন্য প্রস্তাবিত (যদিও এটি আমার ব্যক্তিগত প্রস্তাবনা, বহুল স্বীকৃত নীতি নয়)।
ভ্যারিয়েবল নয় এমন মানগুলি মূলত একই নিয়ম অনুসরণ করে, যদিও আপনি পরে কোনও মেটাচ্যারাক্টরকে উদ্ধৃত করার পরিবর্তে এড়াতে পারেন। একটি সাধারণ উদাহরণ হিসাবে, এতে থাকা একটি ইউআরএল &
শেল দ্বারা ব্যাকগ্রাউন্ড কমান্ড হিসাবে বিশ্লেষণ করবে যদি না মেটাচারাকর পালিয়ে যায় বা উদ্ধৃতি না দেয়:
$ wget http://example.com/q&uack
[1] wget http://example.com/q
-bash: uack: command not found
(অবশ্যই, যদি URL টি উদ্বেগযুক্ত ভেরিয়েবলে থাকে তবে এটিও ঘটে)) স্ট্যাটিক স্ট্রিংয়ের জন্য একক উদ্ধৃতি সর্বাধিক অর্থপূর্ণ হয়, যদিও এখানে কোনও উদ্ধৃতি বা পলায়নের কাজ কাজ করে।
wget 'http://example.com/q&uack' # Single quotes preferred for a static string
wget "http://example.com/q&uack" # Double quotes work here, too (no $ or ` in the value)
wget http://example.com/q\&uack # Backslash escape
wget http://example.com/q'&'uack # Only the metacharacter really needs quoting
শেষ উদাহরণটি আরও একটি দরকারী ধারণাটিও প্রস্তাব করে যা আমি "সওসো কোটিং" বলতে পছন্দ করি। আপনি যদি একক এবং ডাবল উদ্ধৃতি মিশ্রিত করতে চান, আপনি একে অপরের সাথে সংলগ্ন ব্যবহার করতে পারেন। উদাহরণস্বরূপ, নিম্নলিখিত উদ্ধৃত স্ট্রিংগুলি
'$HOME '
"isn't"
' where `<3'
"' is."
টোকনাইজেশন এবং উদ্ধৃতি অপসারণের পরে একক দীর্ঘ স্ট্রিং তৈরি করে একসাথে পিছনে পিছনে আটকানো যেতে পারে।
$ echo '$HOME '"isn't"' where `<3'"' is."
$HOME isn't where `<3' is.
এটি ভয়াবহভাবে স্পষ্টত নয়, তবে এটি একটি সাধারণ কৌশল এবং এটি জেনে রাখা ভাল।
অন্যদিকে, স্ক্রিপ্টগুলি সাধারণত কোনও ls
কিছুর জন্য ব্যবহার করা উচিত নয় । একটি ওয়াইল্ডকার্ড প্রসারিত করতে, কেবল ... এটি ব্যবহার করুন।
$ printf '%s\n' $pattern # not ``ls -1 $pattern''
file1.txt
file_other.txt
$ for file in $pattern; do # definitely, definitely not ``for file in $(ls $pattern)''
> printf 'Found file: %s\n' "$file"
> done
Found file: file1.txt
Found file: file_other.txt
(পরবর্তী উদাহরণে লুপটি সম্পূর্ণভাবে printf
অতিমাত্রায় ব্যবহৃত ; বিশেষত একাধিক তর্ক যুক্ত করেও কাজ stat
করে। তবে একটি ওয়াইল্ডকার্ডের ম্যাচটি লুপ করা একটি সাধারণ সমস্যা, এবং প্রায়শই ভুলভাবে করা হয়))
লুপ ওভার করার জন্য টোকেনগুলির তালিকা বা প্রসারিত করার জন্য একটি ওয়াইল্ডকার্ডের একটি ভেরিয়েবল কম ঘন ঘন দেখা যায়, তাই আমরা মাঝে মাঝে "আপনি কী করছেন তা অবিকল না জানলে" সমস্ত কিছু উদ্ধৃত করার সংক্ষিপ্তসার জানাই।
এখানে সাধারণভাবে উদ্ধৃতিগুলির জন্য একটি তিন-পয়েন্ট সূত্র:
উদ্ধৃতি চিহ্ন
প্রসঙ্গে যেখানে আমরা শব্দ বিভাজন এবং গ্লোববিং দমন করতে চাই। এছাড়াও প্রসঙ্গগুলিতে যেখানে আমরা আক্ষরিককে একটি স্ট্রিং হিসাবে বিবেচনা করতে চাই, রেজেক্স নয়।
একক উদ্ধৃতি
স্ট্রিং লিটারে যেখানে আমরা ইন্টারপোলেশন এবং ব্যাকস্ল্যাশগুলির বিশেষ চিকিত্সা দমন করতে চাই। অন্য কথায়, এমন পরিস্থিতিতে যেখানে ডাবল কোট ব্যবহার করা অনুচিত হবে।
কোন উদ্ধৃতি নেই
প্রসঙ্গে যেখানে আমরা একেবারে নিশ্চিত যে শব্দ বিভাজন বা গ্লোববিংয়ের কোনও সমস্যা নেই বা আমরা শব্দ বিভাজন এবং গ্লোববিং চাই না ।
উদাহরণ
উদ্ধৃতি চিহ্ন
"StackOverflow rocks!"
, "Steve's Apple"
) সহ আক্ষরিক স্ট্রিং"$var"
, "${arr[@]}"
)"$(ls)"
, "`ls`"
)"/my dir/"*
)"single'quote'delimited'string"
)"${filename##*/}"
)একক উদ্ধৃতি
'Really costs $$!'
, 'just a backslash followed by a t: \t'
)'The "crux"'
)$'\n\t'
)$'{"table": "users", "where": "first_name"=\'Steve\'}'
)কোন উদ্ধৃতি নেই
$$
, $?
, $#
ইত্যাদি)((count++))
, "${arr[idx]}"
,"${string:start:length}"
[[ ]]
শব্দের বিভক্তকরণ এবং গ্লোববিংয়ের বিষয়গুলি থেকে মুক্ত যা ভিতরে প্রকাশ (এটি শৈলীর বিষয় এবং মতামত ব্যাপকভাবে পৃথক হতে পারে)for word in $words
)for txtfile in *.txt; do ...
)~
ব্যাখ্যা করতে চাই $HOME
( ~/"some dir"
তবে নয় "~/some dir"
)আরো দেখুন:
"ls" "/"
"ডিরেক্টরিতে সমস্ত স্ট্রিং প্রসঙ্গে" আরও সাবধানতার সাথে যোগ্যতা অর্জন করতে হবে এই বাক্যটি লিখে রুট ডিরেক্টরিতে ফাইলগুলির একটি তালিকা পাবেন ।
[[ ]]
, এবং =
/ এর ডান দিকে কোট করা গুরুত্বপূর্ণ : এটি একটি স্ট্রিংটিকে নিদর্শন / রেজেক্স বা আক্ষরিকভাবে ব্যাখ্যা করার মধ্যে পার্থক্য তৈরি করে। ==
=~
$'...'
) অবশ্যই তাদের নিজস্ব বিভাগ থাকা উচিত।
"ls" "/"
বেশি সাধারণের পরিবর্তে টাইপ করা উচিত ls /
এবং আমি এটিকে নির্দেশিকাগুলির একটি প্রধান ত্রুটি হিসাবে গ্রহণ করি।
case
:)
আমি "$var"
নিরাপদে যেমন উদ্ধৃত তা সাধারণত ব্যবহার করি , যদি না আমি নিশ্চিত $var
না যে এতে স্থান নেই।
আমি $var
লাইনে যোগদানের সহজ উপায় হিসাবে ব্যবহার করি :
lines="`cat multi-lines-text-file.txt`"
echo "$lines" ## multiple lines
echo $lines ## all spaces (including newlines) are zapped
শেল স্ক্রিপ্টে ভেরিয়েবলগুলি ব্যবহারের জন্য উদ্ধৃতিযুক্ত ভেরিয়েবলগুলি উদ্ধৃত হিসাবে ব্যবহার করুন এর অর্থ হল ভেরিয়েবেলে স্পেস বা বিশেষ অক্ষর থাকতে পারে যা আপনার শেল স্ক্রিপ্টের কার্যকারিতা প্রভাবিত করবে না। অন্যথায় যদি আপনি নিজের ভেরিয়েবল নামের কোনও স্পেস বা বিশেষ অক্ষর না রাখার বিষয়ে নিশ্চিত হন তবে আপনি এগুলি "" ছাড়াই ব্যবহার করতে পারেন।
উদাহরণ:
প্রতিধ্বনি "$ url নাম" - (সর্বদা ব্যবহার করা যেতে পারে)
প্রতিধ্বনি "$ url নাম" - (এ জাতীয় পরিস্থিতিতে ব্যবহার করা যায় না তাই এটি ব্যবহারের আগে সাবধানতা অবলম্বন করুন)