Comment puis-je supprimer complètement un élément d'un tableau?


48

unset array[0]supprime l'élément mais quand même si je echo ${array[0]}reçois une valeur nulle, il y a d'autres façons de le faire, mais si un élément d'un tableau contient des espaces comme ci-dessous

array[0]='james young'
array[1]='mary'
array[2]='randy orton'

mais ceux-ci échouent également à faire le travail

array=${array[@]:1} #removed the 1st element

maintenant je veux que le nouveau tableau soit comme

array[0]='mary'
array[1]='randy orton'

Les espaces causent des problèmes après l’affectation et le tableau réel devient comme avec une substitution.

array=(mary randy orton)

4
Non, ce ne sont pas les espaces qui posent problème, mais le manque de citation.
Manatwork

Réponses:


68

Utilisez simplement la syntaxe de tableau sur l'affectation et citez votre variable:

array=("${array[@]:1}") #removed the 1st element

Modifier selon la question dans le commentaire. Pour que $@vous puissiez l'utiliser comme ceci:

set -- "${@:2}" #removed the 1st parameter

8
Notez qu'il ne supprime pas le 1er élément mais l'élément de l'indice 0 et réaffecte les index. Si le premier élément était sur l’indice 12, il ne supprimera rien mais réaffectera les indices de sorte que ce qui était jadis sur l’indice 12 le soit maintenant sur l’indice 0. Ce n’est probablement pas un problème dans le cas du PO mais il convient de le noter pour référence future. Le comportement est différent avec zshles tableaux qui ne sont pas rares contrairement à ksh ou bash.
Stéphane Chazelas

3
Bonjour @ StephaneChazelas. Le singulier de "indices" est " index ". Merci pour votre commentaire!
Steven Lu

3
@manatwork - re: votre édition - pourquoi ne pas utiliser shift?
don_crissti

1
@don_crissti, bon point. Je me suis concentré sur la différence d'indexation et je n'ai pas réfléchi davantage. Nous avions également à l’esprit la situation dans laquelle vous devez supprimer un nombre variable d’articles, par exemple pour conserver exactement le dernier 3: array=("${array[@]: -3}")et set -- "${@: -3}". Si coincé aux indices.
Manatwork

1
shift $[$#-3]pour les 3 derniers est probablement beaucoup plus rapide pour$@
Tino

0

Cela m'a fait réfléchir. Le problème avec sed / awk / tail est qu’ils sont alignés. Après avoir supprimé la première ligne, vous devez écrire toutes les autres lignes de l'espace de modèle dans le fichier.

  • Vous pouvez utiliser les commandes suivantes pour faire ce que vous voulez en quelques secondes.
  • Cela va écrire le fichier entier dans un tableau.
  • Supprimez la première ligne au fur et à mesure que vous la déposez dans le fichier.

    readarray -t aLargeFile < <(cat largefile)
    echo "${aLargeFile[@]:1}" >largefile

Il suffit de changer le largefilepour le nom de votre fichier.


Pourquoi ne pas utiliser à la sed -i 1d largefileplace? Cela fonctionne même pour les fichiers plus volumineux que la RAM + swap
Tino

0

Pour supprimer un élément à un index particulier, nous pouvons utiliser unsetet ensuite copier dans un autre tableau. Juste unsetn'est pas nécessaire dans ce cas. Parce unsetque ne supprime pas l'élément, il définit simplement une chaîne null sur l'index particulier du tableau.

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]}"

La sortie est

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

-1
#!/bin/bash

q=( one two three four five )

echo -e "
  (remove) { [:range:] } <- [:list:]
                | [:range:] => return list with range removed range is in the form of [:digit:]-[:digit:]
"

function remove {
  if [[ $1 =~ ([[:digit:]])(-([[:digit:]]))?   ]]; then
    from=${BASH_REMATCH[1]}
    to=${BASH_REMATCH[3]}
  else
    echo bad range
  fi;shift
  array=( ${@} )
  local start=${array[@]::${from}}
  local rest
  [ -n "$to" ] && rest=${array[@]:((${to}+1))}  || rest=${array[@]:((${from}+1))}
  echo ${start[@]} ${rest[@]}
}

q=( `remove 1 ${q[*]}` )
echo ${q[@]}
~                                                                                                                                                              
~                       

4
Ce serait bien mieux s'il y avait quelque chose à expliquer comment cela fonctionne et pas seulement une goutte de code. Et qu'est-ce qui se passe avec les tildes en bas?
un CVn

3
Sérieusement, vous avez raison. Cela ressemble à cela a été écrit par un hooligan, mais merci. Je n'ai vraiment que l'occasion de glisser ceci entre les jours de portion de hamburger.
MageProspero

Si un élément de q contient des espaces, cela le divisera en plusieurs éléments.
William Everett
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.