বাশ অ্যারে থেকে একটি উপাদান সরান


116

ব্যাশ শেলের একটি অ্যারে থেকে আমার একটি উপাদান সরিয়ে ফেলতে হবে। সাধারণত আমি কেবল করতাম:

array=("${(@)array:#<element to remove>}")

দুর্ভাগ্যক্রমে আমি যে উপাদানটি মুছতে চাই তা পরিবর্তনশীল তাই আমি পূর্ববর্তী কমান্ডটি ব্যবহার করতে পারি না। এখানে একটি উদাহরণ নীচে:

array+=(pluto)
array+=(pippo)
delete=(pluto)
array( ${array[@]/$delete} ) -> but clearly doesn't work because of {}

কোন ধারণা?


কোন শেল? আপনার উদাহরণটি দেখে মনে হচ্ছে zsh
চ্যানার

array=( ${array[@]/$delete} )বাশ প্রত্যাশার মতো কাজ করে আপনি কি কেবল মিস করেছেন =?
কেন শার্প

1
@ কেন, এটি যা চেয়েছিল তা পুরোপুরি নয় - এটি প্রতিটি স্ট্রিং থেকে কোনও ম্যাচ সরিয়ে ফেলবে এবং অ্যারেটিতে খালি স্ট্রিংগুলি ছেড়ে দেবে যেখানে এটি পুরো স্ট্রিংয়ের সাথে মেলে।
টবি স্পিড

উত্তর:


165

নিম্নলিখিতগুলিতে আপনি যেমনটি চান তেমন কাজ করে bashএবং zsh:

$ array=(pluto pippo)
$ delete=pluto
$ echo ${array[@]/$delete}
pippo
$ array=( "${array[@]/$delete}" ) #Quotes when working with strings

যদি একাধিক উপাদান মুছতে হয়:

...
$ delete=(pluto pippo)
for del in ${delete[@]}
do
   array=("${array[@]/$del}") #Quotes when working with strings
done

বিচারকার্য স্থগিত রাখার আদেশ

এই কৌশলটি আসলে $deleteউপাদানগুলির সাথে মেলে উপসর্গগুলি সরিয়ে দেয় , অগত্যা পুরো উপাদানগুলি নয়।

হালনাগাদ

সত্যিকারের কোনও আইটেমটি সরাতে আপনাকে প্রতিটি উপাদানটির সাথে লক্ষ্যটির তুলনা করতে এবং unsetসঠিক ম্যাচটি মুছতে ব্যবহার করে অ্যারের মধ্য দিয়ে চলতে হবে ।

array=(pluto pippo bob)
delete=(pippo)
for target in "${delete[@]}"; do
  for i in "${!array[@]}"; do
    if [[ ${array[i]} = $target ]]; then
      unset 'array[i]'
    fi
  done
done

মনে রাখবেন যে আপনি যদি এটি করেন এবং এক বা একাধিক উপাদান সরিয়ে ফেলা হয় তবে সূচকগুলি আর পূর্ণসংখ্যার ধারাবাহিক ক্রম হবে না।

$ declare -p array
declare -a array=([0]="pluto" [2]="bob")

সহজ ঘটনাটি হ'ল অ্যারেগুলি পরিবর্তনীয় ডেটা স্ট্রাকচার হিসাবে ব্যবহারের জন্য ডিজাইন করা হয়নি। এগুলি প্রাথমিকভাবে একক ভেরিয়েবলের আইটেমের তালিকা সংরক্ষণ করার জন্য ডিলিমিটার হিসাবে অক্ষর নষ্ট না করে (উদাহরণস্বরূপ, সাদা অংশ থাকতে পারে এমন স্ট্রিংগুলির একটি তালিকা সংরক্ষণ করার জন্য) ব্যবহার করা হয়।

ফাঁকগুলি যদি কোনও সমস্যা হয় তবে শূন্যস্থানগুলি পূরণ করার জন্য আপনাকে অ্যারের পুনর্নির্মাণ করতে হবে:

for i in "${!array[@]}"; do
    new_array+=( "${array[i]}" )
done
array=("${new_array[@]}")
unset new_array

43
কেবল এটি জানেন: $ array=(sun sunflower) $ delete=(sun) $ echo ${array[@]/$delete}ফলাফলflower
বার্নস্টেইন

12
মনে রাখবেন যে এটি আসলে একটি প্রতিস্থাপন করছে, সুতরাং অ্যারেটি যদি এমন কিছু হয় (pluto1 pluto2 pippo)তবে আপনি সমাপ্ত হবেন (1 2 pippo)
haridsv

5
লুপের জন্য এটি ব্যবহার করার ক্ষেত্রে কেবল সতর্কতা অবলম্বন করুন কারণ আপনি মুছে ফেলা উপাদানটি একটি খালি উপাদান দিয়ে শেষ করবেন। বিচক্ষণতার জন্য আপনি এর মতো কিছু করতে পারেনfor element in "${array[@]}" do if [[ $element ]]; then echo ${element} fi done
জোয়েল বি

2
তাহলে কীভাবে কেবলমাত্র মিলে যাওয়া উপাদানগুলি মুছবেন?
UmaN

4
দ্রষ্টব্য: এটি সম্পর্কিত মানটিকে কিছুতেই নির্ধারণ করতে পারে তবে উপাদানটি এখনও অ্যারেতে থাকবে।
phil294

29

আপনি অনাকাঙ্ক্ষিত উপাদান ছাড়াই একটি নতুন অ্যারে তৈরি করতে পারেন, তারপরে এটিকে পুরানো অ্যারেতে পুনরায় নিয়োগ করুন। এটি এতে কাজ করে bash:

array=(pluto pippo)
new_array=()
for value in "${array[@]}"
do
    [[ $value != pluto ]] && new_array+=($value)
done
array=("${new_array[@]}")
unset new_array

এই ফলন:

echo "${array[@]}"
pippo

14

মানটি আনসেট করার জন্য এটি সর্বাধিক প্রত্যক্ষ উপায় যদি আপনি জানেন যে এটির অবস্থান।

$ array=(one two three)
$ echo ${#array[@]}
3
$ unset 'array[1]'
$ echo ${array[@]}
one three
$ echo ${#array[@]}
2

3
চেষ্টা করুন echo ${array[1]}, আপনি নাল স্ট্রিং পাবেন। এবং আপনি threeকরতে প্রয়োজন echo ${array[2]}। সুতরাং unsetব্যাশ অ্যারের মধ্যে একটি উপাদান সরানোর অধিকার প্রক্রিয়া নয়।
রাশোক

@ আরশোক, না, ${array[1]+x}নাল স্ট্রিং, তাই array[1]আনসেট নেই। unsetঅবশিষ্ট উপাদানগুলির সূচী পরিবর্তন করে না। আনসেটের জন্য যুক্তিটি উদ্ধৃত করার প্রয়োজন নেই। অ্যারে উপাদান ধ্বংস করার উপায়টি ব্যাশ ম্যানুয়ালটিতে বর্ণিত হয়েছে ।
জার্নো

@ আরশোক আমি দেখতে পাচ্ছি না কেন। ${array[1]}মাত্র 2 আকারের কারণে আপনি এটি বিদ্যমান বলে ধরে নিতে পারবেন না যদি আপনি সূচকগুলি চান তবে পরীক্ষা করুন ${!array[@]}
ড্যানিয়েল সি সোব্রাল

4

এখানে ম্যাপফাইলে এক-লাইন সমাধান রয়েছে:

$ mapfile -d $'\0' -t arr < <(printf '%s\0' "${arr[@]}" | grep -Pzv "<regexp>")

উদাহরণ:

$ arr=("Adam" "Bob" "Claire"$'\n'"Smith" "David" "Eve" "Fred")

$ echo "Size: ${#arr[*]} Contents: ${arr[*]}"

Size: 6 Contents: Adam Bob Claire
Smith David Eve Fred

$ mapfile -d $'\0' -t arr < <(printf '%s\0' "${arr[@]}" | grep -Pzv "^Claire\nSmith$")

$ echo "Size: ${#arr[*]} Contents: ${arr[*]}"

Size: 5 Contents: Adam Bob David Eve Fred

এই পদ্ধতিটি গ্রেপ কমান্ডটি সংশোধন / এক্সচেঞ্জ করে দুর্দান্ত নমনীয়তার অনুমতি দেয় এবং অ্যারেতে কোনও খালি স্ট্রিং ফেলে না।


1
দয়া করে printf '%s\n' "${array[@]}"সেই কুৎসিত IFS/ echoজিনিসটির পরিবর্তে ব্যবহার করুন ।
gniourf_gniourf

মনে রাখবেন যে এটি নতুন লাইনে থাকা ক্ষেত্রগুলিতে ব্যর্থ।
gniourf_gniourf

@ সোকোই আপনি ভুল, কমপক্ষে ৪.৪.১৯ নম্বরে। যুক্তি না দিয়ে -d $'\0'পুরোপুরি সূক্ষ্ম কাজ -dকরে।
নিক্লাস

হ্যাঁ, আমি এটি মিশ্রিত করেছি। দুঃখিত। আমি কি বোঝানো ছিল: -d $'\0'হিসাবে একই -d $'\0 something'বা শুধু -d ''
সোসোইই

$'\0'যদিও স্পষ্টতার জন্য ব্যবহার করতে আঘাত করে না
নিক্লাস

4

এই উত্তরটি বৃহত অ্যারে থেকে একাধিক মান মুছে ফেলার ক্ষেত্রে সুনির্দিষ্ট, যেখানে কার্য সম্পাদন গুরুত্বপূর্ণ।

সর্বাধিক ভোট দেওয়া সমাধানগুলি হ'ল (1) অ্যারের উপর প্যাটার্ন প্রতিস্থাপন, বা (2) অ্যারে উপাদানগুলির উপর পুনরাবৃত্তি। প্রথমটি দ্রুত, তবে কেবলমাত্র সেই উপাদানগুলির সাথে ডিল করতে পারে যার পৃথক উপসর্গ রয়েছে, দ্বিতীয়টির ও (এন * কে), এন = অ্যারের আকার, কে = উপাদানগুলি অপসারণ করতে হবে। সহযোগী অ্যারে আপেক্ষিক নতুন বৈশিষ্ট্য, এবং প্রশ্নটি মূলত পোস্ট করার সময় সম্ভবত এটি সাধারণ ছিল না।

সঠিক মিলের ক্ষেত্রে, বড় এন এবং কে দিয়ে, ও (এন কে) থেকে ও (এন + কে) পর্যন্ত পারফরম্যান্স উন্নতি করা সম্ভব লগ (কে)) । অনুশীলনে, ও (এন) কে এন এর চেয়ে অনেক কম মনে করছে। বেশিরভাগ গতি আপত্তিজনক আইটেমগুলি সরিয়ে ফেলতে চিহ্নিত করতে ব্যবহারের উপর ভিত্তি করে।

পারফরম্যান্স (মোছার জন্য এন-অ্যারে আকার, কে-মান)। ব্যবহারকারীর সময় পারফরম্যান্স পরিমাপ

   N     K     New(seconds) Current(seconds)  Speedup
 1000   10     0.005        0.033             6X
10000   10     0.070        0.348             5X
10000   20     0.070        0.656             9X
10000    1     0.043        0.050             -7%

প্রত্যাশিত হিসাবে, currentসমাধানটি এন * কে এর লিনিয়ার, এবং fastসমাধানটি প্রায় নিম্নতর ধ্রুবক সহ, কে কে লিনিয়ার। fastসমাধান বনাম কিছুটা মন্থর হয়current সমাধান যখন ট = 1, অতিরিক্ত সেটআপ কারণে।

'দ্রুত' সমাধান: অ্যারে = ইনপুটের তালিকা, মুছুন = মুছে ফেলতে মানগুলির তালিকা।

        declare -A delk
        for del in "${delete[@]}" ; do delk[$del]=1 ; done
                # Tag items to remove, based on
        for k in "${!array[@]}" ; do
                [ "${delk[${array[$k]}]-}" ] && unset 'array[k]'
        done
                # Compaction
        array=("${array[@]}")

currentসর্বাধিক ভোট দেওয়া উত্তর থেকে সমাধানের বিরুদ্ধে বেঞ্চমার্কড ।

    for target in "${delete[@]}"; do
        for i in "${!array[@]}"; do
            if [[ ${array[i]} = $target ]]; then
                unset 'array[i]'
            fi
        done
    done
    array=("${array[@]}")

3

এখানে একটি (সম্ভবত খুব বাশ নির্দিষ্ট) সামান্য ফাংশন যা ব্যাশের ভেরিয়েবল ইন্ডিরিশন এবং জড়িত unset; এটি একটি সাধারণ সমাধান যা পাঠ্য প্রতিস্থাপন বা খালি উপাদানগুলি ত্যাগ করার সাথে জড়িত না এবং উদ্ধৃতি / সাদা স্থান ইত্যাদি নিয়ে কোনও সমস্যা নেই

delete_ary_elmt() {
  local word=$1      # the element to search for & delete
  local aryref="$2[@]" # a necessary step since '${!$2[@]}' is a syntax error
  local arycopy=("${!aryref}") # create a copy of the input array
  local status=1
  for (( i = ${#arycopy[@]} - 1; i >= 0; i-- )); do # iterate over indices backwards
    elmt=${arycopy[$i]}
    [[ $elmt == $word ]] && unset "$2[$i]" && status=0 # unset matching elmts in orig. ary
  done
  return $status # return 0 if something was deleted; 1 if not
}

array=(a 0 0 b 0 0 0 c 0 d e 0 0 0)
delete_ary_elmt 0 array
for e in "${array[@]}"; do
  echo "$e"
done

# prints "a" "b" "c" "d" in lines

delete_ary_elmt ELEMENT ARRAYNAMEএটি কোনও $সিগিল ছাড়াই ব্যবহার করুন । উপসর্গের ম্যাচগুলির == $wordজন্য স্যুইচ করুন == $word*; ${elmt,,} == ${word,,}কেস-সংবেদনশীল মিলগুলির জন্য ব্যবহার করুন ; ইত্যাদি, যা-ই বাশ [[সমর্থন করে।

এটি ইনপুট অ্যারের সূচকগুলি নির্ধারণ করে এবং তাদের উপর পিছনে পুনরাবৃত্তি করে কাজ করে (সুতরাং উপাদানগুলি মোছার ফলে পুনরাবৃত্তির ক্রমটি স্ক্রু হয় না)। সূচকগুলি পেতে আপনার নাম অনুসারে ইনপুট অ্যারেটি অ্যাক্সেস করতে হবে যা ব্যাশ ভেরিয়েবল ইন্ডিরেশনের মাধ্যমে করা যেতে পারে x=1; varname=x; echo ${!varname} # prints "1"

আপনি নামের মতো অ্যারে অ্যাক্সেস করতে পারবেন না aryname=a; echo "${$aryname[@]}, এটি আপনাকে একটি ত্রুটি দেয়। আপনি পারবেন না aryname=a; echo "${!aryname[@]}", এটি আপনাকে ভেরিয়েবলের সূচকগুলি দেয় aryname(যদিও এটি অ্যারে নয়)। aryref="a[@]"; echo "${!aryref}"যা কাজ করে তা হ'ল যা অ্যারের উপাদানগুলি মুদ্রণ করবে a, শেল-শব্দ উদ্ধৃতি সংরক্ষণ করবে এবং পুরোপুরি হোয়াইটস্পেস করবে echo "${a[@]}"। তবে এটি কেবল একটি অ্যারের উপাদানগুলি মুদ্রণের জন্য কাজ করে, তার দৈর্ঘ্য বা সূচকগুলি ( aryref="!a[@]"বা aryref="#a[@]"বা "${!!aryref}"বা) মুদ্রণের জন্য নয়"${#!aryref}" , সব তারা ব্যর্থ)।

সুতরাং আমি বাশ ইন্ডিরিয়ারেশনের মাধ্যমে এর নামের সাথে মূল অ্যারেটি অনুলিপি করছি এবং অনুলিপিটি থেকে অনুলিপিগুলি পেয়েছি। বিপরীতে সূচকগুলির উপরে পুনরাবৃত্তি করতে আমি লুপের জন্য একটি সি-স্টাইল ব্যবহার করি। আমি সূচকগুলি অ্যাক্সেস করে ${!arycopy[@]}এবং tacএগুলির সাথে বিপরীত করেও এটি করতে পারতাম , যা catইনপুট লাইনের ক্রম ঘুরিয়ে দেয়।

পরিবর্তনশীল দিকনির্দেশ ছাড়া একটি ফাংশন সমাধান সম্ভবত জড়িত evalথাকতে পারে , যা সেই পরিস্থিতিতে ব্যবহার করা নিরাপদ বা নাও থাকতে পারে (আমি বলতে পারি না)।


এটি প্রায়শই দুর্দান্তভাবে কাজ করে, তবে এটি ফাংশনে প্রারম্ভিক অ্যারেটিকে পুনরায় বিবরণ দেয় না, সুতরাং যখন প্রাথমিক অ্যারেটির মানগুলি অনুপস্থিত থাকে, তখন এটির সূচকগুলিও বিভ্রান্ত হয়। এর অর্থ হ'ল একই অ্যারেতে মুছে ফেলা_রি_েল্টটি করার জন্য পরবর্তী কলটি কার্যকর হবে না (বা ভুল জিনিসগুলি মুছে ফেলবে)। উদাহরণস্বরূপ, আপনি যা পেস্ট করেছেন তার পরে, চালানোর চেষ্টা করুন delete_ary_elmt "d" arrayএবং তারপরে অ্যারেটি পুনরায় মুদ্রণ করুন। আপনি দেখতে পাবেন যে ভুল উপাদানটি সরানো হয়েছে। শেষ উপাদানটি সরিয়ে ফেলার পরেও কখনই কাজ করবে না।
স্কট

2

উপরের উত্তরগুলিতে প্রসারিত করতে, আংশিক মিল না করে নিম্নলিখিতগুলি অ্যারে থেকে একাধিক উপাদান অপসারণ করতে ব্যবহার করা যেতে পারে:

ARRAY=(one two onetwo three four threefour "one six")
TO_REMOVE=(one four)

TEMP_ARRAY=()
for pkg in "${ARRAY[@]}"; do
    for remove in "${TO_REMOVE[@]}"; do
        KEEP=true
        if [[ ${pkg} == ${remove} ]]; then
            KEEP=false
            break
        fi
    done
    if ${KEEP}; then
        TEMP_ARRAY+=(${pkg})
    fi
done
ARRAY=("${TEMP_ARRAY[@]}")
unset TEMP_ARRAY

এর ফলে এতে একটি অ্যারে থাকবে: (দুটি তিনটি তিনটি তিনটি "এক ছয়")


2

যদি কেউ নিজেকে এমন একটি অবস্থানে খুঁজে পান যেখানে তাদের সেট-ই বা সেট-এক্স মানগুলি মনে রাখা দরকার এবং সেগুলি পুনরুদ্ধার করতে সক্ষম হয় তবে দয়া করে এই স্ট্রিটটি পরীক্ষা করে দেখুন যা এটির নিজস্ব স্ট্যাক পরিচালনা করার জন্য প্রথম অ্যারে মুছন সমাধান ব্যবহার করে:

https://gist.github.com/kigster/94799325e39d2a227ef89676eed44cc6


1

আংশিক উত্তর

অ্যারেতে প্রথম আইটেমটি মুছতে

unset 'array[0]'

অ্যারেতে শেষ আইটেমটি মুছতে

unset 'array[-1]'

@gniourf_gniourf এর আর্গুমেন্টের জন্য কোট ব্যবহার করার দরকার নেই unset
জার্নো

2
@ জার্নো: এই উদ্ধৃতিগুলি ব্যবহার করা আবশ্যক: আপনার যদি array0বর্তমান ডিরেক্টরিতে কোনও ফাইলের নাম থাকে তবে যেহেতু array[0]গ্লোব হয় তাই এটি প্রথমে array0আনসেট কমান্ডের আগে প্রসারিত করা হবে ।
gniourf_gniourf

@gniourf_gniourf আপনি সঠিক আছেন এটি বাশ রেফারেন্স ম্যানুয়ালটিতে সংশোধন করা উচিত যা বর্তমানে "আনসেট নাম [সাবস্ক্রিপ্ট] সূচি সাবস্ক্রিপ্টে অ্যারের উপাদানটি ধ্বংস করে" বলে উল্লেখ করে।
জার্নো

1

ব্যবহার unset

নির্দিষ্ট সূচকে কোনও উপাদান অপসারণ করতে, আমরা ব্যবহার করতে unsetপারি এবং তারপরে অন্য অ্যারেতে অনুলিপি করতে পারি। unsetএই ক্ষেত্রে কেবল ন্যায়বিচারের প্রয়োজন নেই। কারণ unsetউপাদানটি সরিয়ে দেয় না এটি অ্যারেতে নির্দিষ্ট সূচকে নাল স্ট্রিং সেট করে।

declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
unset 'arr[1]'
declare -a arr2=()
i=0
for element in "${arr[@]}"
do
    arr2[$i]=$element
    ((++i))
done
echo "${arr[@]}"
echo "1st val is ${arr[1]}, 2nd val is ${arr[2]}"
echo "${arr2[@]}"
echo "1st val is ${arr2[1]}, 2nd val is ${arr2[2]}"

আউটপুট হয়

aa cc dd ee
1st val is , 2nd val is cc
aa cc dd ee
1st val is cc, 2nd val is dd

ব্যবহার :<idx>

আমরা ব্যবহার করে কিছু সেট উপাদান সরিয়ে ফেলতে পারি :<idx>। উদাহরণস্বরূপ যদি আমরা 1 তম উপাদানটি সরাতে চাই তবে আমরা :1নীচে উল্লিখিত হিসাবে ব্যবহার করতে পারি ।

declare -a arr=('aa' 'bb' 'cc' 'dd' 'ee')
arr2=("${arr[@]:1}")
echo "${arr2[@]}"
echo "1st val is ${arr2[1]}, 2nd val is ${arr2[2]}"

আউটপুট হয়

bb cc dd ee
1st val is cc, 2nd val is dd

0

পসিক্স শেল স্ক্রিপ্টের অ্যারে নেই।

সুতরাং সম্ভবত আপনি একটি নির্দিষ্ট উপভাষা যেমন bash, কর্ন শেল বা ব্যবহার করছেন zsh

সুতরাং, আপনার প্রশ্নের উত্তর এখনই দেওয়া যাবে না।

সম্ভবত এটি আপনার পক্ষে কাজ করে:

unset array[$delete]

2
হাই, আমি ব্যাশ শেল এটিএম ব্যবহার করছি। এবং "$ মুছুন" উপাদানটির অবস্থান নয় তবে স্ট্রিং নিজেই। সুতরাং আমি মনে করি না "আনসেট" কাজ করবে
অ্যালেক্স

0

প্রকৃতপক্ষে, আমি কেবল লক্ষ্য করেছি যে শেল সিনট্যাক্সের কিছুটা অন্তর্নির্মিত আচরণ রয়েছে যা অ্যারেটিকে পুনর্গঠন করতে দেয় যখন প্রশ্নটিতে বলা হয়, কোনও আইটেম সরানো উচিত।

# let's set up an array of items to consume:
x=()
for (( i=0; i<10; i++ )); do
    x+=("$i")
done

# here, we consume that array:
while (( ${#x[@]} )); do
    i=$(( $RANDOM % ${#x[@]} ))
    echo "${x[i]} / ${x[@]}"
    x=("${x[@]:0:i}" "${x[@]:i+1}")
done

লক্ষ্য করুন আমরা কীভাবে বাশ ব্যবহার করে অ্যারে তৈরি করেছি x+=() সিনট্যাক্স ?

আপনি এটির সাথে বাস্তবে একাধিক আইটেম যুক্ত করতে পারেন, একবারে পুরো অন্যান্য অ্যারের সামগ্রী।


0

http://wiki.bash-hackers.org/syntax/pe#substring_removal

From AR প্যারামিটার # প্যাটার্ন} # শুরু থেকে সরান

{AR খেলোয়াড় ## প্যাটার্ন} # শুরু থেকে সরান, লোভী ম্যাচ

From AR প্যারামিটার% PATTERN} # শেষ থেকে সরান

, AR প্যারামিটার %% প্যাটার্ন} # শেষ, লোভী ম্যাচ থেকে সরান

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

অ্যারে পরিষ্কার করার জন্য কয়েকটি পৃথক উপায়ে নীচের উদাহরণ দেখুন।

options=("foo" "bar" "foo" "foobar" "foo bar" "bars" "bar")

# remove bar from the start of each element
options=("${options[@]/#"bar"}")
# options=("foo" "" "foo" "foobar" "foo bar" "s" "")

# remove the complete string "foo" in a for loop
count=${#options[@]}
for ((i = 0; i < count; i++)); do
   if [ "${options[i]}" = "foo" ] ; then
      unset 'options[i]'
   fi
done
# options=(  ""   "foobar" "foo bar" "s" "")

# remove empty options
# note the count variable can't be recalculated easily on a sparse array
for ((i = 0; i < count; i++)); do
   # echo "Element $i: '${options[i]}'"
   if [ -z "${options[i]}" ] ; then
      unset 'options[i]'
   fi
done
# options=("foobar" "foo bar" "s")

# list them with select
echo "Choose an option:"
PS3='Option? '
select i in "${options[@]}" Quit
 do
    case $i in 
       Quit) break ;;
       *) echo "You selected \"$i\"" ;;
    esac
 done

আউটপুট

Choose an option:
1) foobar
2) foo bar
3) s
4) Quit
Option? 

আশা করি এইটি কাজ করবে.


0

জেডএসএইচে এটি মৃত সহজ (নোট করুন এটি বোঝার সুবিধার জন্য যেখানে প্রয়োজন সেখানে প্রয়োজনের চেয়ে বেশি ব্যাশ সামঞ্জস্যপূর্ণ বাক্য গঠন ব্যবহার করেছেন):

# I always include an edge case to make sure each element
# is not being word split.
start=(one two three 'four 4' five)
work=(${(@)start})

idx=2
val=${work[idx]}

# How to remove a single element easily.
# Also works for associative arrays (at least in zsh)
work[$idx]=()

echo "Array size went down by one: "
[[ $#work -eq $(($#start - 1)) ]] && echo "OK"

echo "Array item "$val" is now gone: "
[[ -z ${work[(r)$val]} ]] && echo OK

echo "Array contents are as expected: "
wanted=("${start[@]:0:1}" "${start[@]:2}")
[[ "${(j.:.)wanted[@]}" == "${(j.:.)work[@]}" ]] && echo "OK"

echo "-- array contents: start --"
print -l -r -- "-- $#start elements" ${(@)start}
echo "-- array contents: work --"
print -l -r -- "-- $#work elements" "${work[@]}"

ফলাফল:

Array size went down by one:
OK
Array item two is now gone:
OK
Array contents are as expected:
OK
-- array contents: start --
-- 5 elements
one
two
three
four 4
five
-- array contents: work --
-- 4 elements
one
three
four 4
five

দুঃখিত, চেষ্টা করেছি। এটি একটি আশ্বাসযুক্ত অ্যারের জন্য zsh এ কাজ করেনি
ফাল্ক

এটি ঠিক কাজ করে, আমি এটি (আবার) পরীক্ষা করেছি। জিনিস আপনার জন্য কাজ করছে না? আপনি যতটা বিশদে ঠিক তেমন কাজ করতে পারেন নি তা ব্যাখ্যা করুন। আপনি কোন জেডএসএইচ সংস্করণটি ব্যবহার করছেন?
ট্রেভরজ

0

এই বাক্য গঠনটিও রয়েছে, যেমন আপনি যদি ২ য় উপাদান মুছতে চান:

array=("${array[@]:0:1}" "${array[@]:2}")

যা আসলে 2 টি ট্যাবের সংমিশ্রণ। সূচক 0 থেকে প্রথম সূচক 1 (এক্সক্লুসিভ) এবং সূচক 2 থেকে শেষ পর্যন্ত দ্বিতীয়টি।



-1

এটি একটি দ্রুত এবং নোংরা সমাধান যা সাধারণ ক্ষেত্রে কাজ করবে তবে ভেঙে ফেলবে যদি (ক) কোনও রেগেক্সের বিশেষ অক্ষর রয়েছে $delete, বা (খ) কোনও আইটেমের মধ্যে কোনও ফাঁক আছে। দিয়ে শুরু:

array+=(pluto)
array+=(pippo)
delete=(pluto)

হুবহু মিলে সমস্ত এন্ট্রি মুছুন $delete:

array=(`echo $array | fmt -1 | grep -v "^${delete}$" | fmt -999999`)

ফলস্বরূপ echo $array-> পিপ্পো এবং এটি একটি অ্যারে নিশ্চিত করে: echo $array[1]-> পিপ্পো

fmtএটি একটি সামান্য অস্পষ্টতা: fmt -1প্রথম কলামে মোড়ানো (প্রতিটি আইটেমকে তার নিজস্ব লাইনে রাখার জন্য That's একই জায়গায় স্পেসে থাকা আইটেমগুলির সাথে সমস্যা দেখা দেয়)) আইটেমগুলির মধ্যে ফাঁকা স্থানগুলি fmt -999999রেখে আবার এটি একটি লাইন থেকে সরিয়ে রাখে। এটি করার অন্যান্য উপায় আছে যেমন xargs

সংযোজন: আপনি যদি প্রথম ম্যাচটি মুছতে চান তবে বর্ণিত হিসাবে সেড ব্যবহার করুন এখানে করুন :

array=(`echo $array | fmt -1 | sed "0,/^${delete}$/{//d;}" | fmt -999999`)

-1

যেমন কিছু সম্পর্কে:

array=(one two three)
array_t=" ${array[@]} "
delete=one
array=(${array_t// $delete / })
unset array_t

-1

ব্যবহার অ্যারের সূচক সাথে সংঘাত এড়াতে unset- দেখুন https://stackoverflow.com/a/49626928/3223785 এবং https://stackoverflow.com/a/47798640/3223785 আরও তথ্যের জন্য - নিজেই অ্যারে reassign: ARRAY_VAR=(${ARRAY_VAR[@]})

#!/bin/bash

ARRAY_VAR=(0 1 2 3 4 5 6 7 8 9)
unset ARRAY_VAR[5]
unset ARRAY_VAR[4]
ARRAY_VAR=(${ARRAY_VAR[@]})
echo ${ARRAY_VAR[@]}
A_LENGTH=${#ARRAY_VAR[*]}
for (( i=0; i<=$(( $A_LENGTH -1 )); i++ )) ; do
    echo ""
    echo "INDEX - $i"
    echo "VALUE - ${ARRAY_VAR[$i]}"
done

exit 0

[রেফারেন্স: https://tecadmin.net/working-with-array-bash-script/ ]


-2
#/bin/bash

echo "# define array with six elements"
arr=(zero one two three 'four 4' five)

echo "# unset by index: 0"
unset -v 'arr[0]'
for i in ${!arr[*]}; do echo "arr[$i]=${arr[$i]}"; done

arr_delete_by_content() { # value to delete
        for i in ${!arr[*]}; do
                [ "${arr[$i]}" = "$1" ] && unset -v 'arr[$i]'
        done
        }

echo "# unset in global variable where value: three"
arr_delete_by_content three
for i in ${!arr[*]}; do echo "arr[$i]=${arr[$i]}"; done

echo "# rearrange indices"
arr=( "${arr[@]}" )
for i in ${!arr[*]}; do echo "arr[$i]=${arr[$i]}"; done

delete_value() { # value arrayelements..., returns array decl.
        local e val=$1; new=(); shift
        for e in "${@}"; do [ "$val" != "$e" ] && new+=("$e"); done
        declare -p new|sed 's,^[^=]*=,,'
        }

echo "# new array without value: two"
declare -a arr="$(delete_value two "${arr[@]}")"
for i in ${!arr[*]}; do echo "arr[$i]=${arr[$i]}"; done

delete_values() { # arraydecl values..., returns array decl. (keeps indices)
        declare -a arr="$1"; local i v; shift
        for v in "${@}"; do 
                for i in ${!arr[*]}; do
                        [ "$v" = "${arr[$i]}" ] && unset -v 'arr[$i]'
                done
        done
        declare -p arr|sed 's,^[^=]*=,,'
        }
echo "# new array without values: one five (keep indices)"
declare -a arr="$(delete_values "$(declare -p arr|sed 's,^[^=]*=,,')" one five)"
for i in ${!arr[*]}; do echo "arr[$i]=${arr[$i]}"; done

# new array without multiple values and rearranged indices is left to the reader

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