किसी तत्व को Bash सरणी से निकालें


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
नोट: यह संबंधित मान को कुछ भी नहीं सेट कर सकता है, लेकिन तत्व अभी भी सरणी में होगा।
दर्शन २

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बैश एरे में किसी तत्व को निकालने के लिए सही तंत्र नहीं है।
राशोक

@rashok, नहीं, ${array[1]+x}अशक्त स्ट्रिंग है, इसलिए परेशान array[1]है। unsetशेष तत्वों के अनुक्रमित को नहीं बदलता है। परेशान के लिए तर्क का हवाला देते हुए जरूरत नहीं है। सरणी तत्व को नष्ट करने का तरीका बैश मैनुअल में वर्णित है ।
जर्नो

@rashok मैं नहीं देखता क्यों नहीं। आप मान नहीं सकते हैं कि ${array[1]}सिर्फ इसलिए मौजूद है कि आकार 2 है। यदि आप सूचकांक चाहते हैं, तो जांचें ${!array[@]}
डैनियल सी। सोबरल

4

यहाँ Mapfile के साथ एक-लाइन समाधान है:

$ 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

यह विधि grep कमांड को संशोधित / एक्सचेंज करके महान लचीलेपन की अनुमति देती है और सरणी में कोई भी खाली स्ट्रिंग नहीं छोड़ती है।


1
कृपया printf '%s\n' "${array[@]}"उस बदसूरत IFS/ echoचीज़ के बजाय उपयोग करें ।
गनीउर_ग्निरॉफ

ध्यान दें कि यह उन फ़ील्ड्स के साथ विफल हो जाता है जिनमें newlines होते हैं।
गनीउर्फ_निगियॉर्फ

@Socowi आप गलत हैं, कम से कम bash 4.4.19 पर। -d $'\0'पूरी तरह से ठीक काम करता है जबकि -dबिना तर्क के नहीं होता है।
निकल्स होल्म

आह हाँ, मैंने इसे मिलाया। माफ़ करना। मेरा मतलब था: -d $'\0'जैसा है -d $'\0 something'या वैसा ही है -d ''
सोकोवि

$'\0'स्पष्टता के लिए उपयोग करने के लिए चोट नहीं करता है
निकल्स होल्म

4

यह उत्तर बड़े सरणियों से कई मानों को हटाने के मामले के लिए विशिष्ट है, जहां प्रदर्शन महत्वपूर्ण है।

सबसे अधिक मतदान समाधान एक सरणी पर (1) पैटर्न प्रतिस्थापन हैं, या (2) सरणी तत्वों पर पुनरावृत्ति करते हैं। पहला तेज़ है, लेकिन केवल उन तत्वों से निपट सकता है जिनमें अलग-अलग उपसर्ग हैं, दूसरे में O (n * k), n = सरणी आकार, k = तत्व निकालने हैं। साहचर्य सरणी सापेक्ष नई विशेषता है, और जब प्रश्न मूल रूप से पोस्ट किया गया था तो यह आम नहीं हो सकता था।

सटीक मिलान मामले के लिए, बड़े n और k के साथ, O (n k) से O (n + k log (k)) तक के प्रदर्शन में सुधार करना संभव है । व्यवहार में, O (n) k को n से बहुत कम मान रहा है। हटाए जाने वाले आइटमों की पहचान करने के लिए अधिकांश गति अप साहचर्य सरणी का उपयोग करने पर आधारित है।

प्रदर्शन (n-array size, k-values ​​to delete)। उपयोगकर्ता समय का प्रदर्शन माप सेकंड

   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समाधान N * K के लिए रैखिक है, और fastसमाधान K के लिए व्यावहारिक रूप से रैखिक है, बहुत कम निरंतर के साथ। fastसमाधान थोड़ी धीमी बनाम है currentसमाधान जब k = 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

यहाँ bash वैरिएबल इनडायरेक्शन और (लिटिल बैश-स्पेसिफिक) लिटिल फंक्शन है 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 पर काम करेंगे (या गलत काम को हटा देगा)। उदाहरण के लिए, आपने जो कुछ भी चिपकाया है, उसे चलाने का प्रयास करें 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

यह एक सरणी में परिणाम देगा: (दो onetwo तीन तीनfour "एक छह")


2

अगर कोई भी खुद को ऐसी स्थिति में पाता है, जहां उन्हें सेट-ई या सेट -x मानों को याद रखने और उन्हें पुनर्स्थापित करने में सक्षम होना चाहिए, तो कृपया इस जिस्ट की जांच करें, जो इसे स्टैक करने के लिए पहले सरणी विलोपन समाधान का उपयोग करता है:

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


1

केवल आंशिक उत्तर

सरणी में पहला आइटम हटाने के लिए

unset 'array[0]'

सरणी में अंतिम आइटम को हटाने के लिए

unset 'array[-1]'

@gniourf_gniourf के तर्क के लिए उद्धरण का उपयोग करने की आवश्यकता नहीं है unset
जर्नो

2
@jarno: इन उद्धरणों का उपयोग किया जाना चाहिए: यदि आपके पास array0वर्तमान निर्देशिका में एक फ़ाइल है , तो चूंकि array[0]यह ग्लोब है, इसलिए इसे सबसे array0पहले unset कमांड से पहले विस्तारित किया जाएगा ।
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

POSIX शेल स्क्रिप्ट में एरेज़ नहीं है।

तो शायद आप एक विशिष्ट बोली का उपयोग कर रहे हैं जैसे 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

$ {PARAMETER # PATTERN} # शुरुआत से हटा दें

$ {PARAMETER ## PATTERN} # शुरुआत से दूर, लालची मैच

$ {PARAMETER% PATTERN} # अंत से हटा दें

$ {PARAMETER %% PATTERN} # अंत से दूर, लालची मैच

पूर्ण हटाने वाले तत्व को करने के लिए, आपको एक if स्टेटमेंट के साथ एक unset कमांड करना होगा। यदि आप अन्य चर से उपसर्गों को हटाने या सरणी में व्हाट्सएप का समर्थन करने के बारे में परवाह नहीं करते हैं, तो आप बस उद्धरण छोड़ सकते हैं और छोरों के बारे में भूल सकते हैं।

एक सरणी को साफ करने के कुछ अलग तरीकों के लिए नीचे दिए गए उदाहरण देखें।

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

ZSH में यह मृत आसान है (ध्यान दें कि यह जहां आवश्यक हो उससे अधिक बैश संगत सिंटैक्स का उपयोग करता है जहां समझ में आसानी के लिए संभव है):

# 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

क्षमा करें, बस कोशिश की। यह एक assoziative सरणी के लिए zsh में काम नहीं किया
Falk

यह ठीक काम करता है, मैंने अभी इसका परीक्षण किया (फिर से)। चीजें आपके लिए काम नहीं कर रही हैं? कृपया बताएं कि आपने जितना विस्तार से काम किया है, उतना वास्तव में क्या नहीं है। ZSH संस्करण क्या आप उपयोग कर रहे हैं?
trevorj

0

यदि आप दूसरा तत्व हटाना चाहते हैं, तो यह सिंटैक्स भी है:

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

जो वास्तव में 2 टैब का संयोजन है। इंडेक्स 0 से इंडेक्स 1 (अनन्य) और 2 इंडेक्स 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पहले कॉलम पर लपेटता है (प्रत्येक आइटम को अपनी लाइन पर रखने के लिए। यही वह स्थान है जहाँ रिक्त स्थान में आइटम के साथ समस्या उत्पन्न होती है।) fmt -999999इसे वापस एक लाइन पर वापस लाती है, आइटम के बीच के रिक्त स्थान को वापस लाती है। ऐसा करने के अन्य तरीके हैं, जैसे कि xargs

परिशिष्ट: यदि आप केवल पहले मैच को हटाना चाहते हैं, तो यहां दिए अनुसार, sed का उपयोग करें :

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 अधिक जानकारी के लिए - खुद को सरणी पुन: असाइन: 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
क्या आप हमें अपने उत्तर के बारे में बताने के लिए कुछ टिप्पणी या विवरण जोड़ सकते हैं?
माइकल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.