Подтвердить что ты не робот

Удалить последний элемент из массива

Я хочу удалить последнюю запись в моем массиве, и я хочу, чтобы массив показал мне, что у меня есть 1 запись меньше, когда я использую ${#array[@]}. Это текущая строка, которую я использую:

unset GreppedURLs[${#GreppedURLs[@]} -1]

Пожалуйста, исправьте меня и покажите мне правильный путь.

4b9b3361

Ответ 1

У вас есть (почти) правильный для нерезких индексированных массивов ¹:

unset 'arr[${#arr[@]}-1]'

(Обратите внимание на одинарные кавычки: они предотвращают расширение пути).

Демо:

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

3

for a in "${arr[@]}"; do echo "$a"; done
a
b
c
unset 'arr[${#arr[@]}-1]'
for a in "${arr[@]}"; do echo "$a"; done
a
b

Punchline

echo ${#arr[@]}
2

(GNU bash, версия 4.2.8 (1) -release (x86_64-pc-linux-gnu))


¹ @Wil предоставил отличный ответ, который работает для всех типов массивов

Ответ 2

Вы должны удалить пробел до -1.

Ответ 3

Если вы хотите получить ответ, который не будет есть ваши котята, попробуйте следующее:

array=([1]=1 {2..5} [10]=6);
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5" [10]="6}")'
index=("${!array[@]}");
# declare -a index='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="10")'
unset 'array[${index[@]: -1}]';
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5")'

И там у вас есть - удаление последнего элемента. Теперь я представлю гораздо более легкий ответ, который, вероятно, отвечает вашим потребностям, но имеет оговорку:

array=([1]=1 {2..5} [10]=6);
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5" [10]="6}")'
array=("${array[@]::${#array[@]}-1}");
# declare -a array='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5")'

Эта версия имеет ярлык. Он повторно индексирует массив и удаляет последний элемент. К сожалению, вы также можете видеть, что индекс не поддерживается. Значения и их порядок были. Если вам не нужен индекс, это, вероятно, тот ответ, который вам нужен.

Оба вышеупомянутых ответа будут также работать над bash 4 Ассоциативными массивами.

-

Выбранный ответ небезопасен. Вот пример:

array=([1]=1 {2..5} [10]=6);
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [5]="5" [10]="6")'
unset 'arr[${#arr[@]}-1]';
# declare -a array='([1]="1" [2]="2" [3]="3" [4]="4" [10]="6")'

Хорошо, так как вы можете видеть, что он отключает элемент с индексом 5, потому что он неправильно вычисляет индекс последнего элемента массива. Он потерпел неудачу, потому что он работал с предположением, что все массивы основаны на нулевом значении и не являются разреженными. Этот ответ терпит неудачу в массивах, начиная с чего угодно, кроме нуля, массивов, которые являются разреженными, и, очевидно, должен завершиться неудачей для ассоциативного массива с "fubar" для последнего элемента.

Ответ 4

Для любого индексированного массива (разреженного или нет), поскольку bash 4.3+ (и ksh93 +), это самый простой из решений:

unset 'array[-1]'

Кавычки необходимы, чтобы избежать расширения оболочки в bash, если -1 является арифметическим выражением или переменной. Это также работает правильно:

a=3; unset 'arr[ a - 4 * 1 ]'

Но не будет работать, если unquoted (''), поскольку * будет расширен до списка файлов в текущем рабочем каталоге ($pwd).

Для более старых версий bash: это работает с bash 3.0 для нерезких массивов:

unset 'arr[ ${#arr[@]}-1 ]'

Пример:

$ arr=( {a..i} ); declare -p arr  
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [7]="h")
$ unset 'arr[ ${#arr[@]}-1 ]'; declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g")

Это работает не для разреженных массивов (с некоторыми отверстиями):

$ arr=( {a..g} [9]=i ); declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [9]="i")
$ unset 'arr[ ${#arr[@]}-1 ]'; declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g" [9]="i")

Это происходит потому, что количество элементов (${#arr[@]}) равно 8 и 8-1 равно 7.
Таким образом, команда будет отменена arr[7], которая не существует. Ничего не сделано.

Решение, которое также работает для ассоциативных массивов (во всем, что это может означать "последний элемент" в несортированном списке) заключается в создании нового массива индексов. Затем используйте последний индекс, чтобы удалить этот элемент.

Предполагается, что arr уже определен (для bash 3.0 +):

$ index=( "${!arr[@]}" )          # makes index non-sparse.
$ unset 'arr[${index[@]}-1]'      # unset the last index.
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e" [5]="f" [6]="g")

Немного более портативный (работает в ksh93), который выглядит уродливым, решение:

$ arr=( {a..e} [9]=i )
$ index=( "${!arr[@]}" )
$ unset "arr[  ${index[${#index[@]}-1]}  ]"   # Yes, double quotes.
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c" [3]="d" [4]="e")   

Или (опять же, двойные кавычки для ksh):

$ unset "arr[${index[@]: -1}]"

Если вы хотите избежать пробела и отрицательного числа, сделайте его переменной:

$ a="-1"; unset "arr[${index[@]:a}]"