বাশ সম্পূর্ণ হওয়ার প্রসঙ্গে $ {অ্যারে [*] us বনাম $ {অ্যারে [@] about সম্পর্কে একটি বিভ্রান্তি


90

আমি প্রথমবারের জন্য ব্যাশের সমাপ্তি লিখতে গিয়ে ছুরিকাঘাত করছি এবং ব্যাশ অ্যারে ( ${array[@]}এবং ${array[*]}) এর দুটি উপায় অবলম্বন করার বিষয়ে আমি কিছুটা বিভ্রান্ত হয়েছি ।

এখানে কোডের প্রাসঙ্গিক অংশটি রয়েছে (এটি কাজ করে, তবে আমি এটি আরও ভালভাবে বুঝতে চাই):

_switch()
{
    local cur perls
    local ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew}
    COMPREPLY=()
    cur=${COMP_WORDS[COMP_CWORD]}
    perls=($ROOT/perls/perl-*)
    # remove all but the final part of the name
    perls=(${perls[*]##*/})

    COMPREPLY=( $( compgen -W "${perls[*]} /usr/bin/perl" -- ${cur} ) )
}

বাশের ডকুমেন্টেশন বলে :

অ্যারের কোনও উপাদান $ {নাম [সাবস্ক্রিপ্ট] using ব্যবহার করে রেফারেন্স করা যেতে পারে} শেলের ফাইল নাম সম্প্রসারণ অপারেটরগুলির সাথে দ্বন্দ্ব এড়াতে ধনুর্বন্ধনী প্রয়োজন সাবস্ক্রিপ্ট যদি '@' বা '*' হয় তবে শব্দটি অ্যারের নামের সমস্ত সদস্যের কাছে প্রসারিত হয়। এই সাবস্ক্রিপ্টগুলি কেবল তখনই পৃথক হয় যখন শব্দটি ডাবল কোটের মধ্যে উপস্থিত হয়। যদি শব্দটি ডাবল-কোট করা থাকে তবে $ {নাম [*] আইএফএস ভেরিয়েবলের প্রথম অক্ষর দ্বারা পৃথক পৃথক প্রতিটি অ্যারে সদস্যের মান সহ একটি শব্দে প্রসারিত হয় এবং $ {নাম [@] name নামের প্রতিটি উপাদানকে প্রসারিত করে একটি পৃথক শব্দ।

এখন আমি মনে করি আমি বুঝতে পারি যে compgen -Wসম্ভাব্য বিকল্পগুলির একটি ওয়ার্ডলিস্টযুক্ত একটি স্ট্রিং প্রত্যাশা করে, তবে এই প্রসঙ্গে আমি "{{নাম [@] name নামের প্রতিটি উপাদানকে পৃথক শব্দের" মানে কী বোঝায় তা বুঝতে পারি না।

দীর্ঘ গল্প সংক্ষিপ্ত: ${array[*]}কাজ; ${array[@]}না আমি কেন জানতে চাই এবং আমি ঠিক কী ${array[@]}প্রসারিত হবে তা আরও ভালভাবে বুঝতে চাই ।

উত্তর:


120

(এই Kaleb Pederson এর উত্তরে আমার মন্তব্যের সম্প্রসারণ হয় - একটি সাধারণ চিকিৎসার জন্য যে উত্তর দেখার [@]বনাম [*]।)

যখন বাশ (বা অন্য কোনও শেল) একটি কমান্ড লাইনকে বিশ্লেষণ করে, তখন এটি "শব্দের" একটি সিরিজে বিভক্ত হয়ে যায় (যা আমি পরে গোলযোগ এড়াতে "শেল-শব্দগুলি" বলব)। সাধারণত শেল-শব্দগুলি স্পেস (বা অন্যান্য সাদা স্থান) দ্বারা পৃথক করা হয়, তবে স্পেসগুলি এড়ানো বা উদ্ধৃতি দিয়ে শেল-শব্দে অন্তর্ভুক্ত করা যেতে পারে। ডাবল-কোটায় [@]এবং- [*]এক্সপেন্ডেড অ্যারেগুলির মধ্যে পার্থক্য হ'ল "${myarray[@]}"অ্যারের প্রতিটি উপাদানকে পৃথক শেল-শব্দের হিসাবে বিবেচনা করা হয়, অন্যদিকে অ্যারেগুলির "${myarray[*]}"সমস্ত উপাদান ফাঁকা স্থান দ্বারা পৃথক হওয়া একটি শেল-শব্দের ফলাফল হয় (বা প্রথম চরিত্রটি যাই হোক না কেন IFS)।

সাধারণত, [@]আচরণটি আপনি যা চান তা হয়। মনে করুন আমাদের রয়েছে perls=(perl-one perl-two)এবং ব্যবহার করুন ls "${perls[*]}"- এটি সমান ls "perl-one perl-two", যা নামের একক ফাইলের সন্ধান করবে perl-one perl-two, যা সম্ভবত আপনি চেয়েছিলেন তা নয়। ls "${perls[@]}"এর সমতুল্য ls "perl-one" "perl-two", যা দরকারী কিছু করার সম্ভাবনা বেশি।

সমাপ্তির শব্দের একটি তালিকা সরবরাহ করা (যা আমি শেল-শব্দের সাথে বিভ্রান্তি এড়াতে কম্প-শব্দগুলি বলব) এর compgenচেয়ে আলাদা; -Wবিকল্প Comp-শব্দের একটি তালিকা লাগে, কিন্তু এটা শূণ্যস্থান দ্বারা পৃথক Comp-শব্দের সঙ্গে একটি একক শেল শব্দ আকারে হতে হবে। নোট করুন যে কমান্ড অপশনগুলি সর্বদা আর্গুমেন্ট গ্রহণ করে (কমপক্ষে আমি যতদূর জানি) একটি একক শেল শব্দটি গ্রহণ করে - অন্যথায় বিকল্পের আর্গুমেন্টগুলি কখন শেষ হয় তা জানার উপায় নেই এবং নিয়মিত কমান্ড আর্গুমেন্ট (/ অন্যান্য) বিকল্প পতাকা) শুরু।

আরো বিস্তারিত:

perls=(perl-one perl-two)
compgen -W "${perls[*]} /usr/bin/perl" -- ${cur}

সমান:

compgen -W "perl-one perl-two /usr/bin/perl" -- ${cur}

... যা আপনি যা চান তা করে। অন্য দিকে,

perls=(perl-one perl-two)
compgen -W "${perls[@]} /usr/bin/perl" -- ${cur}

সমান:

compgen -W "perl-one" "perl-two /usr/bin/perl" -- ${cur}

... যা সম্পূর্ণ বোকামি: "পার্ল-ওয়ান" হ'ল-ডাব্লু পতাকার সাথে সংযুক্ত একমাত্র কম-শব্দ এবং প্রথম আসল যুক্তি - যা কমপ্লেনটি স্ট্রিংটি সম্পূর্ণ হওয়ার জন্য গ্রহণ করবে - "পার্ল-টু" / usr / বিন / পার্ল "। আমি কমপেনকে অভিযোগ করার জন্য আশা করব যে এটি অতিরিক্ত যুক্তি ("-" এবং যা কিছু $ কারের মধ্যে রয়েছে) দেওয়া হয়েছে, তবে দৃশ্যত এটি কেবল তাদের উপেক্ষা করে।


4
এটি দুর্দান্ত; ধন্যবাদ আমি সত্যিই এটি আরও জোরে ফুঁকতে চাইছি, তবে এটি কমপক্ষে এটি কেন কাজ করে নি তা স্পষ্ট করে।
টেলিমাচাস

61

আপনার শিরোনাম ${array[@]}বনাম সম্পর্কে ${array[*]}জিজ্ঞাসা করে তবে আপনি $array[*]বনাম সম্পর্কে জিজ্ঞাসা করুন $array[@]যা কিছুটা বিভ্রান্তিকর। আমি উভয় জবাব দেব:

আপনি যখন অ্যারে ভেরিয়েবলটি উদ্ধৃত করেন এবং @সাবস্ক্রিপ্ট হিসাবে ব্যবহার করেন, অ্যারের প্রতিটি উপাদান তার সম্পূর্ণ সামগ্রীতে প্রসারণ করা হয় নির্ধারিত সাদা অংশ (প্রকৃতপক্ষে কোনও একটি $IFS) that সামগ্রীর মধ্যে উপস্থিত থাকতে পারে। যখন আপনি *সাবস্ক্রিপ্ট হিসাবে তারকাচিহ্ন ( ) ব্যবহার করেন ( এটি উদ্ধৃত হোক বা না তা নির্বিশেষে) এটিতে প্রতিটি অ্যারের উপাদানটির বিষয়বস্তু বিচ্ছিন্ন করে নির্মিত নতুন সামগ্রীতে প্রসারিত হতে পারে $IFS

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

#!/bin/sh

myarray[0]="one"
myarray[1]="two"
myarray[3]="three four"

echo "with quotes around myarray[*]"
for x in "${myarray[*]}"; do
        echo "ARG[*]: '$x'"
done

echo "with quotes around myarray[@]"
for x in "${myarray[@]}"; do
        echo "ARG[@]: '$x'"
done

echo "without quotes around myarray[*]"
for x in ${myarray[*]}; do
        echo "ARG[*]: '$x'"
done

echo "without quotes around myarray[@]"
for x in ${myarray[@]}; do
        echo "ARG[@]: '$x'"
done

এবং এখানে এটি ফলাফল:

with quotes around myarray[*]
ARG[*]: 'one two three four'
with quotes around myarray[@]
ARG[@]: 'one'
ARG[@]: 'two'
ARG[@]: 'three four'
without quotes around myarray[*]
ARG[*]: 'one'
ARG[*]: 'two'
ARG[*]: 'three'
ARG[*]: 'four'
without quotes around myarray[@]
ARG[@]: 'one'
ARG[@]: 'two'
ARG[@]: 'three'
ARG[@]: 'four'

আমি ব্যক্তিগতভাবে সাধারণত চান "${myarray[@]}"। এখন, আপনার প্রশ্নের দ্বিতীয় অংশটির উত্তর দিতে, ${array[@]}বনাম $array[@]

আপনি উদ্ধৃত করেছেন এমন ব্যাশ ডক্সের উদ্ধৃতি:

শেলের ফাইল নাম সম্প্রসারণ অপারেটরগুলির সাথে দ্বন্দ্ব এড়াতে ধনুর্বন্ধনী প্রয়োজন

$ myarray=
$ myarray[0]="one"
$ myarray[1]="two"
$ echo ${myarray[@]}
one two

কিন্তু, আপনি যখন করেন $myarray[@], ডলার চিহ্নটি দৃly়ভাবে আবদ্ধ হয় myarrayযাতে এটির আগে মূল্যায়ন করা হয় [@]। উদাহরণ স্বরূপ:

$ ls $myarray[@]
ls: cannot access one[@]: No such file or directory

তবে, ডকুমেন্টেশনে উল্লিখিত হিসাবে, বন্ধনীগুলি ফাইলের নাম প্রসারণের জন্য, সুতরাং আসুন এটি চেষ্টা করুন:

$ touch one@
$ ls $myarray[@]
one@

এখন আমরা দেখতে পাচ্ছি যে ফাইলের নাম সম্প্রসারণ প্রসারণের পরে ঘটেছিল $myarray

এবং আরও একটি নোট, $myarrayসাবস্ক্রিপ্ট ছাড়াই অ্যারের প্রথম মানটিতে প্রসারিত:

$ myarray[0]="one four"
$ echo $myarray[5]
one four[5]

4
আরো দেখুন এই সংক্রান্ত কিভাবে IFSআউটপুট ভিন্নভাবে উপর নির্ভর করে প্রভাবিত @বনাম *এবং বনাম unquoted উদ্ধৃত।
ডেনিস উইলিয়ামসন

আমি ক্ষমাপ্রার্থী, যেহেতু এ প্রসঙ্গে এটি বেশ গুরুত্বপূর্ণ, তবে আমি সবসময়ই বোঝাতে চেয়েছিলাম ${array[*]}বা ${array[@]}। ধনুর্বন্ধকের অভাব ছিল কেবল অসতর্কতা। এর বাইরেও, আপনি কি ব্যাখ্যা করতে পারবেন যে কমান্ডটি ${array[*]}প্রসারিত হবে compgen? অর্থাৎ, সেই প্রসঙ্গে তার অ্যারের প্রতিটি উপাদানকে আলাদা করে অ্যারে প্রসারিত করার অর্থ কী?
টেলিমাচাস

এটি অন্য কোনও উপায়ে রাখতে, আপনি (প্রায় প্রতিটি উত্সের মতো) বলে থাকেন যে ${array[@]}এটি সাধারণত যাওয়ার উপায়। আমি যা বোঝার চেষ্টা করছি তা কেন এই ক্ষেত্রে কেবল ${array[*]} কাজ করে।
টেলিমাচাস

4
এর কারণ হচ্ছে -ডাব্লু বিকল্পের সাথে সরবরাহিত ওয়ার্ডলিস্টটি অবশ্যই একটি একক শব্দ হিসাবে দেওয়া উচিত (যা আইএফএসের উপর ভিত্তি করে বিভক্ত হয়)। যদি এটি কমপেজের কাছে হস্তান্তর করার আগে পৃথক শব্দের মধ্যে বিভক্ত হয়ে যায় (যা [@] যা করে), কমপেজ মনে করবে যে কেবল প্রথমটি -W এর সাথে যায়, এবং বাকীগুলি নিয়মিত যুক্তি হয় (এবং আমি মনে করি এটি কেবল একটি যুক্তির প্রত্যাশা করে, এবং তাই বাধা পাবে)।
গর্ডন ডেভিসন

@ গর্ডন: একটি উত্তরে এটি সরান, এবং আমি এটি গ্রহণ করব। এটাই আমি সত্যিই জানতে চেয়েছিলাম। ধন্যবাদ (বিটিডব্লিউ, এটি একটি সুস্পষ্ট উপায়ে ঝাঁকুনি দেয় না It এটি নিঃশব্দে বাধা দেয় - যা ভুল হয়েছে তা জানতে অসুবিধা হয়))
টেলিম্যাকাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.