Как удалить точный элемент в массиве bash?

Я пытаюсь удалить только первое появление любого ключевого слова из массива bash.

ARRAY=(foo bar and any number of keywords)
keywords=(red, rednet, rd3.0)

Я удаляю ключевое слово следующим образом: ARRAY=( ${ARRAY[@]/"$keyword"/} ) тогда, если "красный" является первым найденным ключевым словом, он удалит "красный" из обоих ключевых слов и вернет "foo bar net" вместо "foo bar rednet".

Изменить: вот пример, надеюсь, это прояснит.

for keyword in ${ARRAY[@]}; do
      if [ "$keyword" = "red" ] || [ "$keyword" = "rd3.0" ] || [ "$keyword" = "rednet" ]; then
           # HERE IS TROUBLE
           ARRAY=( ${ARRAY[@]/"$keyword"/} )
           echo "ARRAY is now ${ARRAY[@]}"
           break
      fi
 done

Что, если ARRAY=(red rednet rd3.0) возвращает net rd3.0 вместо rednet rd3.0

Если я использую unset,: unset ${ARRAY["$keyword"]} bash жалуется, если rd3.0 находится в массиве: :syntax error: invalid arithmetic operator (error token is ".0") Каков безопасный способ сбросить или удалить только точное совпадение из массива?


person mateor    schedule 10.01.2013    source источник


Ответы (2)


Используйте команду unset со значением массива index, примерно так:

#!/usr/bin/env bash
ARRAY=(foo bar any red alpha number of keywords rd3.0 and)
keywords=(red, rednet, rd3.0)

index=0
for keyword in ${ARRAY[@]}; do
      if [ "$keyword" = "red" ] || [ "$keyword" = "rd3.0" ] || [ "$keyword" = "rednet" ]; then
           # HERE IS TROUBLE
           # ARRAY=( ${ARRAY[@]/"$p"/} )
           unset ARRAY[$index]
           echo "ARRAY is now: ${ARRAY[@]}"
           break
      fi
      let index++
 done
person higuaro    schedule 10.01.2013
comment
Я понимаю. Я могу это сделать. Огромное спасибо! - person mateor; 11.01.2013
comment
Стоит отметить, что это фактически не удаляет элемент из массива, а просто устанавливает его в пустое значение. Итак, если вы запустите a=( a b c ); unset a[1]; echo ${a[1]}, вы получите не c, как можно было бы ожидать, а то, что находится в пустом элементе. Чтобы действительно удалить элемент, вы должны следовать за unset чем-то вроде a=( ${a[@] }, чтобы сдвинуть другие элементы вперед, чтобы занять место пустых. - person William Everett; 03.08.2014
comment
Чтобы сбросить индексы после цикла: ARRAY=("${ARRAY[@]}") - person Angel; 18.04.2021

Во-первых: вы должны использовать кавычки вокруг ваших ключей в массивах. Это позволяет избежать проблем, например, с rd3.0.

Как это:

ARRAY=("foo" "bar" "and" "any" "number" "of" "keywords")
keywords=("red", "rednet", "rd3.0")

На мой взгляд, вам нужно скопировать массив, а затем использовать цикл for для фильтрации ключевых слов. Выход из цикла for после первой успешной фильтрации. После этого скопируйте его обратно без пустых элементов массива. См. это короткие примеры (параграф 10).

Подробнее о массивах: http://tldp.org/LDP/abs/html/arrays.html (все, что вам когда-либо понадобится)

person erik    schedule 10.01.2013
comment
В моем сценарии это фактически копия исходного массива. Я просто сократил его здесь. Я также использую циклы for, чтобы перебирать его и выходить. Я перешел по вашей ссылке и видел ее много раз ... мой вопрос не столько о массивах, сколько об обработке текста, я думаю. Я получаю строку, подобную этой первоначально красной сети Rednet rd3.0. Должен ли я переформатировать, чтобы вставить двоеточие, как вы думаете? - person mateor; 11.01.2013
comment
Под двоеточием вы случайно не имеете в виду кавычки? Двоеточие :, кавычки "". - person user; 09.10.2013
comment
Майкл Кьёрлинг: Давно, но я не вижу двоеточий в своем посте. Вы, кажется, правы. :-) - person erik; 09.10.2013