বাশ শেলের মধ্যে $ {var}, "$ var", এবং "$ {var}" এর মধ্যে পার্থক্য কী?


133

কি শিরোনাম বলেছেন: এটা কি একটি পরিবর্তনশীল encapsulate মানে {}, ""অথবা "{}? "আমি এই সম্পর্কে কোন ব্যাখ্যা অনলাইন খুঁজে পেতে সক্ষম হয়েছে না - আমি প্রতীক ব্যবহার করার জন্য ব্যতীত তাদের পড়ুন করা, সক্ষম হয়েছে না যা কিছুই ফল দেয় না।

এখানে একটি উদাহরণ:

declare -a groups

groups+=("CN=exampleexample,OU=exampleexample,OU=exampleexample,DC=example,DC=com")
groups+=("CN=example example,OU=example example,OU=example example,DC=example,DC=com")

এই:

for group in "${groups[@]}"; do
    echo $group
done

এর থেকে অনেক বেশি ভিন্ন প্রমাণিত হয়:

for group in $groups; do
    echo $group
done

এবং এই:

for group in ${groups}; do
    echo $group
done

অ্যারে প্রতিটি উপাদান দিয়ে পুনরাবৃত্তি করতে: কেবল প্রথমটিই আমি যা চাই তা পূরণ করে। আমি মধ্যে পার্থক্য উপর সত্যিই স্পষ্ট নই $groups, "$groups", ${groups}এবং "${groups}"। যদি কেউ এটি ব্যাখ্যা করতে পারে তবে আমি এটির প্রশংসা করব।

অতিরিক্ত প্রশ্ন হিসাবে - এই এনক্যাপসুলেশনগুলি উল্লেখ করার জন্য কি কেউ গ্রহণযোগ্য উপায় জানেন?


উত্তর:


228

ধনুর্বন্ধনী ( $varবনাম ${var})

বেশিরভাগ ক্ষেত্রে $varএবং ${var}একই রকম:

var=foo
echo $var
# foo
echo ${var}
# foo

ধনুর্বন্ধনী শুধুমাত্র অভিব্যক্তি মধ্যে অস্পষ্টতা সমাধান করার জন্য প্রয়োজন:

var=foo
echo $varbar
# Prints nothing because there is no variable 'varbar'
echo ${var}bar
# foobar

উদ্ধৃতি ( $varবনাম "$var"বনাম)"${var}" )

আপনি যখন কোনও ভেরিয়েবলের চারপাশে ডাবল উক্তি যুক্ত করেন, আপনি শেলটিকে একটি একক শব্দের হিসাবে বিবেচনা করতে বলুন, তাতে সাদা অংশ থাকলেও:

var="foo bar"
for i in "$var"; do # Expands to 'for i in "foo bar"; do...'
    echo $i         #   so only runs the loop once
done
# foo bar

নিম্নলিখিত ব্যবহারের সাথে সেই আচরণের তুলনা করুন:

var="foo bar"
for i in $var; do # Expands to 'for i in foo bar; do...'
    echo $i       #   so runs the loop twice, once for each argument
done
# foo
# bar

$varবনাম হিসাবে ${var}, ধনুর্বন্ধনী শুধুমাত্র ছত্রভঙ্গ করার জন্য প্রয়োজন, উদাহরণস্বরূপ:

var="foo bar"
for i in "$varbar"; do # Expands to 'for i in ""; do...' since there is no
    echo $i            #   variable named 'varbar', so loop runs once and
done                   #   prints nothing (actually "")

var="foo bar"
for i in "${var}bar"; do # Expands to 'for i in "foo barbar"; do...'
    echo $i              #   so runs the loop once
done
# foo barbar

নোট করুন যে "${var}bar"উপরের দ্বিতীয় উদাহরণেও লিখিত হতে পারে "${var}"bar, এক্ষেত্রে আপনার আর ধনুর্বন্ধনী প্রয়োজন নেই, অর্থাত্‍ "$var"bar। তবে, আপনার স্ট্রিংয়ে প্রচুর উক্তি থাকলে এই বিকল্প ফর্মগুলি পড়া শক্ত হয়ে যেতে পারে (এবং তাই বজায় রাখা শক্ত)। এই পৃষ্ঠাটি বাশ-এ উদ্ধৃতি দেওয়ার জন্য একটি ভাল ভূমিকা সরবরাহ করে।

অ্যারে ( $varবনাম $var[@]বনাম ${var[@]})

এখন আপনার অ্যারের জন্য। বাশ ম্যানুয়াল অনুসারে :

সাবস্ক্রিপ্ট ছাড়াই একটি অ্যারে ভেরিয়েবল উল্লেখ করা 0 এর সাবস্ক্রিপ্ট সহ অ্যারে উল্লেখ করার সমতুল্য।

অন্য কথায়, আপনি যদি একটি সূচক সরবরাহ না করে থাকেন তবে আপনি []অ্যারের প্রথম উপাদানটি পাবেন:

foo=(a b c)
echo $foo
# a

যা ঠিক তেমনই

foo=(a b c)
echo ${foo}
# a

একটি অ্যারের সমস্ত উপাদান পেতে, আপনাকে @সূচক হিসাবে যেমন ব্যবহার করতে হবে , যেমন ${foo[@]}। অ্যারেগুলির সাথে ধনুর্বন্ধনী আবশ্যক কারণ এগুলি ছাড়া শেলটি $fooপ্রথমে অংশটি প্রসারিত করবে এবং অ্যারের প্রথম উপাদানটি একটি আক্ষরিক দ্বারা অনুসরণ করবে [@]:

foo=(a b c)
echo ${foo[@]}
# a b c
echo $foo[@]
# a[@]

এই পৃষ্ঠাটি বাশের অ্যারেগুলির জন্য একটি ভাল ভূমিকা।

উদ্ধৃতি পুনর্বিবেচনা ( ${foo[@]}বনাম "${foo[@]}")

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

foo=("the first" "the second")
for i in "${foo[@]}"; do # Expands to 'for i in "the first" "the second"; do...'
    echo $i              #   so the loop runs twice
done
# the first
# the second

ডাবল উদ্ধৃতি ব্যতীত আচরণের সাথে এর বিপরীতে:

foo=("the first" "the second")
for i in ${foo[@]}; do # Expands to 'for i in the first the second; do...'
    echo $i            #   so the loop runs four times!
done
# the
# first
# the
# second

3
আরও একটি কেস রয়েছে: ${var:?}যা ভেরিয়েবলটি সেট না করা বা সেট না করা অবস্থায় ত্রুটি সরবরাহ করবে। REF: github.com/koalaman/shellcheck/wiki/SC2154
নাম Nguyen

4
@NamNguyen আপনি অন্যান্য ধরনের সম্পর্কে কথা বলতে চান পরামিতি সম্প্রসারণ : অন্তত এক ডজন আরো আছে ${parameter:-word}, ${parameter:=word}, ${parameter#word}, ${parameter/pattern/string}, ইত্যাদি। আমি মনে করি সেগুলি এই উত্তরের বাইরে নয়।
এইসুইটসস ব্ল্যাকনট

আসলে, ডাবল উদ্ধৃতিগুলির আলোচনাটি একধরণের অসম্পূর্ণ। আরও দেখুন stackoverflow.com/questions/10067266/...
tripleee

11

টি এল; ডিআর

আপনি যে সমস্ত উদাহরণ দিয়েছেন তা হ'ল বাশ শেল সম্প্রসারণের ভিন্নতা । একটি নির্দিষ্ট ক্রমে বিস্তৃতি ঘটে এবং কিছুতে নির্দিষ্ট ব্যবহারের ক্ষেত্রে থাকে have

টোকেন ডিলিমিটার হিসাবে ধনুর্বন্ধনী

${var}সিনট্যাক্স প্রাথমিকভাবে দ্ব্যর্থক টোকেন delimiting জন্য ব্যবহৃত হয়। উদাহরণস্বরূপ, নিম্নলিখিত বিবেচনা করুন:

$ var1=foo; var2=bar; var12=12
$ echo $var12
12
$ echo ${var1}2
foo2

অ্যারে বিস্তারে ধনুর্বন্ধনী

ধনুর্বন্ধনীগুলির জন্য একটি অ্যারের উপাদানগুলি অ্যাক্সেস করতে এবং অন্যান্য বিশেষ বিস্তারের প্রয়োজন হয় । উদাহরণ স্বরূপ:

$ foo=(1 2 3)

# Returns first element only.
$ echo $foo
1

# Returns all array elements.
$ echo ${foo[*]}
1 2 3

# Returns number of elements in array.
$ echo ${#foo[*]}
3

Tokenization

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

$ var1=foo; var2=bar; count_params () { echo $#; }

# Variables are interpolated into a single string.
$ count_params "$var1 $var2"
1

# Each variable is quoted separately, created two arguments.
$ count_params "$var1" "$var2"
2

@প্রতীক চেয়ে ভিন্নভাবে মূল্য উদ্ধৃতি সাথে মিথস্ক্রিয়া *। বিশেষ করে:

  1. $@ "[ই] এক থেকে শুরু করে অবস্থানগত পরামিতিগুলিতে এক্সপ্যান্ডস্।
  2. একটি অ্যারেতে, [[i] f শব্দটি ডাবল-কোটেড ${name[*]}হয়, প্রতিটি অ্যারে সদস্যের মান আইএফএস ভেরিয়েবলের প্রথম অক্ষর দ্বারা পৃথক হয়ে ${name[@]}একটি শব্দে প্রসারিত হয় এবং নামের প্রতিটি উপাদানকে পৃথক শব্দের মধ্যে প্রসারিত করে "

আপনি নিম্নলিখিত হিসাবে এটি কর্মে দেখতে পারেন:

$ count_params () { echo $#; }
$ set -- foo bar baz 

$ count_params "$@"
3

$ count_params "$*"
1

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


7

আপনাকে অ্যারে এবং সাধারণ ভেরিয়েবলগুলির মধ্যে পার্থক্য করতে হবে - এবং আপনার উদাহরণটি অ্যারে ব্যবহার করছে।

প্লেইন ভেরিয়েবলের জন্য:

  • $varএবং ${var}ঠিক সমতুল্য।
  • "$var"এবং "${var}"ঠিক সমতুল্য।

যাইহোক, দুটি জুটি সব ক্ষেত্রে 100% অভিন্ন নয়। নীচের আউটপুট বিবেচনা করুন:

$ var="  abc  def  "
$ printf "X%sX\n" $var
XabcX
XdefX
$ printf "X%sX\n" "${var}"
X  abc  def  X
$

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

অ্যারে সহ, বিধি দুটি একই এবং পৃথক।

  • যদি groupsঅ্যারে, রেফারেন্সিং হয় $groupsবা রেফারেন্সিংয়ের ${groups}অনুরূপ হয় ${groups[0]}তবে অ্যারের জিরোথ উপাদান।
  • রেফারেন্সিং রেফারেন্সিংয়ের "${groups[@]}"সাথে সাদৃশ্যপূর্ণ "$@"; এটি অ্যারের স্বতন্ত্র উপাদানগুলিতে ব্যবধানকে সংরক্ষণ করে এবং অ্যারের প্রতিটি উপাদানকে মূল্য হিসাবে একটি মান প্রদান করে।
  • ${groups[@]}ডাবল উদ্ধৃতি ব্যতীত রেফারেন্সিং ব্যবধান সংরক্ষণ করে না এবং অ্যারের উপাদানগুলির চেয়ে কিছু উপাদান ফাঁকা থাকলে আরও মানগুলি প্রবর্তন করতে পারে।

উদাহরণ স্বরূপ:

$ groups=("abc def" "  pqr  xyz  ")
$ printf "X%sX\n" ${groups[@]}
XabcX
XdefX
XpqrX
XxyzX
$ printf "X%sX\n" "${groups[@]}"
Xabc defX
X  pqr  xyz  X
$ printf "X%sX\n" $groups
XabcX
XdefX
$ printf "X%sX\n" "$groups"
Xabc defX
$

*পরিবর্তে ব্যবহার করে @সাবটলি বিভিন্ন ফলাফল বাড়ে।

কোনও bashস্ক্রিপ্টে আর্গুমেন্টগুলি কীভাবে পুনরায় করা যায় তা দেখুন ।


3

প্রথম অনুচ্ছেদের দ্বিতীয় বাক্যে প্যারামিটার সম্প্রসারণ মধ্যে man bashবলছেন,

প্যারামিটারের নাম বা প্রতীকটি প্রসারিত হতে পারে ব্রেসগুলিতে আবদ্ধ থাকতে পারে, যা alচ্ছিক তবে ভেরিয়েবলটিকে অক্ষরগুলি থেকে তত্ক্ষণাত্ প্রসারিত করা যায় যা নামের অংশ হিসাবে ব্যাখ্যা করা যায় protect

যা আপনাকে জানায় যে নামটি কেবল ধনুর্বন্ধনী এবং মূল উদ্দেশ্যটি নামটি শুরু এবং শেষ হয় তা স্পষ্ট করা:

foo='bar'
echo "$foobar"
# nothing
echo "${foo}bar"
barbar

আপনি যদি আরও পড়েন তবে আবিষ্কার করুন,

যখন প্যারামিটারটি একাধিক ডিজিটের সাথে অবস্থানগত প্যারামিটার হয় তখন বন্ধনীগুলির প্রয়োজন হয় ...

পরীক্ষা করা যাক:

$ set -- {0..100}
$ echo $22
12
$ echo ${22}
20

হাহ। ঝরঝরে। আমি সত্যই জানতাম না যে এটি লেখার আগে (আমার আগে 9 টির বেশি অবস্থানিক প্যারামিটার ছিল না))

অবশ্যই শক্তিশালী প্যারামিটার সম্প্রসারণ বৈশিষ্ট্যগুলি করতে আপনার ধনুর্বন্ধনী প্রয়োজন

${parameter:-word}
${parameter:=word}
${parameter:?word}
 [read the section for more]

পাশাপাশি অ্যারে সম্প্রসারণ।


3

একটি সম্পর্কিত মামলা উপরে আচ্ছাদিত না। একটি খালি ভেরিয়েবলের উদ্ধৃতি দিয়ে জিনিসগুলি পরিবর্তিত হবে বলে মনে হচ্ছে test -n। এটি infoপাঠ্যের জন্য বিশেষত উদাহরণ হিসাবে দেওয়া হয়েছে coreutils, তবে সত্যই ব্যাখ্যা করা হয়নি:

16.3.4 String tests
-------------------

These options test string characteristics.  You may need to quote
STRING arguments for the shell.  For example:

     test -n "$V"

  The quotes here prevent the wrong arguments from being passed to
`test' if `$V' is empty or contains special characters.

আমি বিস্তারিত ব্যাখ্যা শুনতে চাই। আমার পরীক্ষার বিষয়টি নিশ্চিত করে -zএবং -nএকই ফলাফল এড়াতে এবং ফিরে আসতে আমি এখন সমস্ত স্ট্রিং পরীক্ষার জন্য আমার পরিবর্তনশীলগুলি উদ্ধৃত করছি ।

$ unset a
$ if [ -z $a ]; then echo unset; else echo set; fi
unset
$ if [ -n $a ]; then echo set; else echo unset; fi    
set                                                   # highly unexpected!

$ unset a
$ if [ -z "$a" ]; then echo unset; else echo set; fi
unset
$ if [ -n "$a" ]; then echo set; else echo unset; fi
unset                                                 # much better

2

ভাল, আমি জানি যে একটি ভেরিয়েবলের এনক্যাপসুলেশন আপনাকে এমন কিছু দিয়ে কাজ করতে সহায়তা করে:

${groups%example}

বা সিনট্যাক্স এর মতো, যেখানে আপনি মানটি ফেরত দেওয়ার আগে আপনার ভেরিয়েবলের সাথে কিছু করতে চান।

এখন, আপনি যদি আপনার কোড দেখতে পান তবে সমস্ত যাদুটি ভিতরে রয়েছে

${groups[@]}

জাদুটি সেখানে রয়েছে কারণ আপনি কেবল লিখতে পারবেন না: $groups[@]

আপনি আপনার ভেরিয়েবলটি ভিতরে রাখছেন {}কারণ আপনি বিশেষ অক্ষর []এবং ব্যবহার করতে চান @। আপনি কেবল আপনার ভেরিয়েবলের নাম বা কল করতে পারবেন না: @বা something[]এগুলি অন্য ক্রিয়াকলাপ এবং নামের জন্য সংরক্ষিত অক্ষর।


এটি ডাবল উদ্ধৃতিগুলির অত্যন্ত তাৎপর্যপূর্ণ অর্থ উল্লেখ করতে ব্যর্থ হয় এবং সেগুলি ছাড়াই কোডটি কীভাবে মূলত ভেঙে যায়।
ট্রিপলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.