শেল ভেরিয়েবলের চারপাশে উদ্ধৃতিগুলি কখন लपेटবেন?


183

কেউ আমাকে শেল স্ক্রিপ্টে ভেরিয়েবলের চারপাশে উদ্ধৃতিগুলি আবদ্ধ করা উচিত কিনা তা বলতে পারেন?

উদাহরণস্বরূপ, নিম্নলিখিতটি সঠিক:

xdg-open $URL 
[ $? -eq 2 ]

অথবা

xdg-open "$URL"
[ "$?" -eq "2" ]

আর যদি তাই হয় তবে কেন?


2
এছাড়াও দেখুন unix.stackexchange.com/questions/171346/…
ট্রিপলি

এই প্রশ্নটি অনেকগুলি সদৃশ হয়, যার মধ্যে অনেকগুলি ভেরিয়েবল সম্পর্কে নয়, তাই আমি "ভেরিয়েবল" এর পরিবর্তে "মান" এ ফিরে এসেছি। আমি আশা করি এটি আরও বেশি লোককে এই বিষয়টি সন্ধান করতে সহায়তা করে।
ট্রিপলি

1
পুনরায় উল্লিখিত সম্পাদনাটি কী হবে?
ট্রিপলি


উত্তর:


130

সাধারণ নিয়ম: যদি তা ফাঁকা থাকে বা ফাঁকা স্থান (বা সত্যই কোনও সাদা জায়গা) বা বিশেষ অক্ষর (ওয়াইল্ডকার্ড) থাকতে পারে তবে এটিকে উদ্ধৃত করুন। ফাঁকা জায়গাগুলির সাথে স্ট্রিং উদ্ধৃতি না দেওয়ার ফলে প্রায়শই শেল অনেকের মধ্যে একক যুক্তিকে বিচ্ছিন্ন করে তোলে।

$?এটি একটি সংখ্যাসূচক মান হওয়ায় উদ্ধৃতিগুলির দরকার নেই। কিনা $URLএটা কি আপনি সেখানে অনুমতি উপর নির্ভর করে এবং আপনি এখনও একটি আর্গুমেন্ট চান কিনা এটা খালি যদি প্রয়োজন।

আমি সর্বদা অভ্যাসের বাইরে স্ট্রিংগুলি উদ্ধৃত করি যেহেতু এটি সেভাবেই নিরাপদ।


2
মনে রাখবেন যে "স্পেসস" এর অর্থ "যেকোন সাদা স্থান" means
উইলিয়াম পার্সেল

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

11
আপনি যদি আইএফএসের মান জানেন না, তবে তা যাই হোক না কেন তা উদ্ধৃত করুন। যদি IFS=0, তবে echo $?খুব অবাক হতে পারে।
চার্লস ডাফি

3
প্রসঙ্গের ভিত্তিতে উদ্ধৃতি, মানগুলি আপনি কী প্রত্যাশা করেন তার উপর নয়, অন্যথায় আপনার বাগগুলি আরও খারাপ হবে। উদাহরণস্বরূপ, আপনি নিশ্চিত যে আপনার কোনও পাথের কোনও স্থানই ফাঁকা নেই, তাই আপনি ভাবেন যে আপনি লিখতে পারেন cp $source1 $source2 $dest, তবে যদি কিছু অপ্রত্যাশিত কারণে destসেট না হয়ে যায় তবে তৃতীয় যুক্তিটি কেবল অদৃশ্য হয়ে যায় এবং এটি আপনাকে দেওয়ার পরিবর্তে নিঃশব্দে অনুলিপি source1করে দেবে source2ফাঁকা গন্তব্যের জন্য যথাযথ ত্রুটি (যেমনটি যদি আপনি প্রতিটি যুক্তির উদ্ধৃতি দিয়ে থাকেন)।
ডেরেক ভাইট

3
quote it if...চিন্তার প্রক্রিয়াটি পিছনের দিকে রয়েছে - কোটগুলি আপনার যখন প্রয়োজন হয় তখন যুক্ত হয় না, এগুলি এমন কিছু যা আপনার যখন প্রয়োজন হয় তখন মুছে ফেলা হয়। ডাবল উদ্ধৃতি ব্যবহার করার প্রয়োজন না হলে (যেমন ভেরিয়েবলটি প্রসারিত করতে) বা কোনও উদ্ধৃতি ব্যবহার করার প্রয়োজন না হয় (যেমন গ্লোব্বিং এবং ফাইলের নাম সম্প্রসারণ) to
এড মর্টন

91

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

একক উদ্ধৃতি তাদের মধ্যবর্তী শব্দটিকে ভারব্যাটিক রক্ষা করে। শেলটি স্ট্রিংটি একেবারেই স্পর্শ না করে তা নিশ্চিত করার দরকার হলে এটি যথাযথ সরঞ্জাম। সাধারণত যখন আপনার ভেরিয়েবল ইন্টারপোলেশন প্রয়োজন হয় না তখন এটি পছন্দের উদ্ধৃতি প্রক্রিয়া।

$ 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করে। তবে একটি ওয়াইল্ডকার্ডের ম্যাচটি লুপ করা একটি সাধারণ সমস্যা, এবং প্রায়শই ভুলভাবে করা হয়))

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


1
এই (অংশ) একটা উত্তর আমি পোস্ট একটি বৈচিত্র হয় সংশ্লিষ্ট প্রশ্ন । আমি এটি এখানে আটকানো করছি কারণ এটি সংক্ষিপ্ত এবং যথেষ্ট নির্দিষ্টভাবে সংজ্ঞায়িত করা হয়েছে যে এই বিশেষ সমস্যার জন্য একটি প্রমিত প্রশ্ন হয়ে উঠতে পারে।
ট্রিপলি

4
আমি নোট করব যে এটি আইটেম # 0 এবং mywiki.wooledge.org/BashPitfalls এ সাধারণ বাশের ভুলগুলির সংগ্রহের একটি পুনরাবৃত্তি থিম । এই তালিকার অনেকগুলি পৃথক আইটেম মূলত এই সমস্যাটি সম্পর্কে bas
ট্রিপলি

26

এখানে সাধারণভাবে উদ্ধৃতিগুলির জন্য একটি তিন-পয়েন্ট সূত্র:

উদ্ধৃতি চিহ্ন

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

একক উদ্ধৃতি

স্ট্রিং লিটারে যেখানে আমরা ইন্টারপোলেশন এবং ব্যাকস্ল্যাশগুলির বিশেষ চিকিত্সা দমন করতে চাই। অন্য কথায়, এমন পরিস্থিতিতে যেখানে ডাবল কোট ব্যবহার করা অনুচিত হবে।

কোন উদ্ধৃতি নেই

প্রসঙ্গে যেখানে আমরা একেবারে নিশ্চিত যে শব্দ বিভাজন বা গ্লোববিংয়ের কোনও সমস্যা নেই বা আমরা শব্দ বিভাজন এবং গ্লোববিং চাই না


উদাহরণ

উদ্ধৃতি চিহ্ন

  • সাদা স্পেস ( "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")

আরো দেখুন:


3
এই নির্দেশিকা অনুসারে, "ls" "/" "ডিরেক্টরিতে সমস্ত স্ট্রিং প্রসঙ্গে" আরও সাবধানতার সাথে যোগ্যতা অর্জন করতে হবে এই বাক্যটি লিখে রুট ডিরেক্টরিতে ফাইলগুলির একটি তালিকা পাবেন ।
উইলিয়াম পার্সেল

5
ইন [[ ]], এবং =/ এর ডান দিকে কোট করা গুরুত্বপূর্ণ : এটি একটি স্ট্রিংটিকে নিদর্শন / রেজেক্স বা আক্ষরিকভাবে ব্যাখ্যা করার মধ্যে পার্থক্য তৈরি করে। ===~
বেনিয়ামিন ডাব্লু।

6
একটি ভাল ওভারভিউ, তবে @ বেঞ্জামিন ডাব্লু। এর মন্তব্যগুলি সংহত করার জন্য মূল্যবান এবং এএনএসআই সি-উদ্ধৃত স্ট্রিংগুলি ( $'...') অবশ্যই তাদের নিজস্ব বিভাগ থাকা উচিত।
mklement0

3
@ এমকিলেমেন্ট ০, তারা সমতুল্য। এই নির্দেশিকাগুলি নির্দেশ করে যে আপনার সর্বদা "ls" "/"বেশি সাধারণের পরিবর্তে টাইপ করা উচিত ls /এবং আমি এটিকে নির্দেশিকাগুলির একটি প্রধান ত্রুটি হিসাবে গ্রহণ করি।
উইলিয়াম পার্সেল

4
জন্য কোন উদ্বৃতি আপনি পরিবর্তনশীল নিয়োগ বা যোগ হতে পারে case:)
PesaThe

4

আমি "$var"নিরাপদে যেমন উদ্ধৃত তা সাধারণত ব্যবহার করি , যদি না আমি নিশ্চিত $varনা যে এতে স্থান নেই।

আমি $varলাইনে যোগদানের সহজ উপায় হিসাবে ব্যবহার করি :

lines="`cat multi-lines-text-file.txt`"
echo "$lines"                             ## multiple lines
echo $lines                               ## all spaces (including newlines) are zapped

চূড়ান্ত মন্তব্যটি কিছুটা বিভ্রান্তিকর; নতুন লাইনগুলি কার্যকরভাবে স্থানগুলি দিয়ে প্রতিস্থাপন করা হয়, কেবল সরানো হয় না।
ট্রিপলি

-1

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

উদাহরণ:

প্রতিধ্বনি "$ url নাম" - (সর্বদা ব্যবহার করা যেতে পারে)

প্রতিধ্বনি "$ url নাম" - (এ জাতীয় পরিস্থিতিতে ব্যবহার করা যায় না তাই এটি ব্যবহারের আগে সাবধানতা অবলম্বন করুন)

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