Получение ключа, соответствующего определенному значению в ассоциативном массиве

Если вы доверяете выводу вашей команды rhc, вы можете просто получить его:

. <(rhc env list -a <app-name>)

Это приведет к тому, что источник (выполнит )каждую строку, созданную rhc.

Как написано выше, код определяет переменные, но не экспортирует их. Мы могли бы это исправить, но приведенный ниже код безопаснее и выполняет экспорт.

Исходная команда .ожидает файл в качестве аргумента. Чтобы преобразовать вывод rhcв файл -, подобный объекту, мы используем подстановку процесса:<(...).

Для большей безопасности используйте:

while read -r line; do declare -x "$line"; done < <(rhc env list -a <app-name>)

Здесь мы используем подстановку процесса, <(...), в сочетании с перенаправлением ввода, <, так что цикл whileсчитывает вывод rhc. Пространство между первым и вторым <необходимо, :не не его опускают.

Опция -xдля declareуказывает bash экспортировать переменную.

Изменение порядка

В соответствии с комментарием ниже, команду rhcможно поместить в строку над циклом whileчерез:

tmpvar=$(rhc env list -a <app-name>)
while read -r line; do declare -x "$line"; done <<<"$tmpvar"

<<<создает здесь строку . В данном случае это означает, что $tmpvarпредоставляется как вход для цикла while.

2
11.01.2020, 17:44
3 ответа

Оболочка zsh(отмечает, что zshимел поддержку ассоциативных массивов за десятилетия до того, какbash)имел операторы для этого:

  • ${hash[(R)pattern]}расширяется до значений , соответствующих шаблону.
  • ${(k)hash[(R)pattern]}расширяется до клавиш, где соответствующее значение соответствует шаблону.
  • ${(k)hash[(Re)string]}То же самое, за исключением того, что строка обрабатывается как eстрока xact, а не шаблон, даже если она содержит подстановочные знаки.

Так:

print -r -- ${(k)array[(Re)red]}

Будут напечатаны не -пустые ключи со значением red.

Чтобы включить пустые ключи, используйте:

$ typeset -A array
$ array=(a blue b red c yellow '' red)
$ printf '<%s>\n' "${(@k)array[(Re)red]}"
<>
<b>
1
27.01.2020, 22:07

Это некрасиво, но можно:

for k in "${!array[@]}"; do
    [[ ${array[$k]} == red ]] && printf '%s\n' "$k"
done

Это будет перебирать индексы массива и проверять каждый, если их значение равно red, если да, то будет напечатан индекс.

В качестве альтернативы и тоже некрасиво можно было бы использоватьsed:

declare -p array | sed -n 's/.*\[\(.*\)\]="red".*/\1/p'

Это напечатает массив, как объявлено, и найдет индекс для значения redи распечатает его.

0
27.01.2020, 22:07

Предположим, что вы хотите получить список ключей, соответствующих определенному значению, и хотите сохранить этот список в массиве:

#!/bin/bash

declare -A hash
hash=(
    [k1]="hello world"
    [k2]="hello there"
    [k3]="hello world"
    [k4]=bumblebees
)

string="hello world"

keys=()
for key in "${!hash[@]}"; do
    if [[ ${hash[$key]} == "$string" ]]; then
        keys+=( "$key" )
    fi
done

printf 'Keys with value "%s":\n' "$string"
printf '\t%s\n' "${keys[@]}"

Это просматривает список ключей и проверяет значение, соответствующее каждому ключу, на соответствие строке, которую мы ищем. Если есть совпадение, мы сохраняем ключ в массиве keys.

В конце выводятся найденные ключи.

Вывод этого скрипта будет

Keys with value "hello world":
        k1
        k3
2
27.01.2020, 22:07

Теги

Похожие вопросы