insert into customer_keyskill(customerID, keySkillID)
select 2,1 from dual
where not exists (
select customerID from customer_keyskill
where customerID = 2
and keySkillID = 1 )
Bash 4 изначально поддерживает эту функцию. Убедитесь, что хэшбэнг вашего скрипта - #! / Usr / bin / env bash
или #! / Bin / bash
, чтобы вы не использовали sh
. Убедитесь, что вы либо выполняете свой сценарий напрямую, либо выполняете сценарий
с помощью сценария bash
. (На самом деле не выполнение сценария Bash с Bash происходит , и действительно сбивает с толку!)
Вы объявляете ассоциативный массив, выполнив:
declare -A animals
Вы можете заполнить его с элементами, использующими обычный оператор присваивания массива. Например, если вы хотите получить карту животное [звук (ключ)] = животное (значение)
:
animals=( ["moo"]="cow" ["woof"]="dog")
или объединить их:
declare -A animals=( ["moo"]="cow" ["woof"]="dog")
Затем используйте их, как обычные массивы. Используйте animals ['key'] = 'value'
, чтобы установить значение, "$ {animals [@]}"
, чтобы развернуть значения, и "$ {! Animals" [@]} "
(обратите внимание на !
), чтобы раскрыть ключи. Не забудьте процитировать их:
echo "${animals[moo]}"
for sound in "${!animals[@]}"; do echo "$sound - ${animals[$sound]}"; done
До bash 4 у вас не было ассоциативных массивов. Не используйте eval
для имитации . Избегайте eval
как чумы, потому что это чума сценариев оболочки. Самая важная причина в том, что eval
обрабатывает ваши данные как исполняемый код (есть и много других причин).
Прежде всего : подумайте об обновлении до bash 4. Это значительно упростит вам весь процесс.
Если есть причина, по которой вы не можете выполнить обновление, объявите
гораздо более безопасным вариантом. Он не оценивает данные, как код bash, как eval
, и, как таковой, не позволяет с такой легкостью внедрять произвольный код.
Давайте подготовим ответ, введя понятия:
Во-первых, косвенное обращение.
$ animals_moo=cow; sound=moo; i="animals_$sound"; echo "${!i}"
cow
Во-вторых, declare
:
$ sound=moo; animal=cow; declare "animals_$sound=$animal"; echo "$animals_moo"
cow
Объедините их:
# Set a value:
declare "array_$index=$value"
# Get a value:
arrayGet() {
local array=$1 index=$2
local i="${array}_$index"
printf '%s' "${!i}"
}
Давайте использовать его:
$ sound=moo
$ animal=cow
$ declare "animals_$sound=$animal"
$ arrayGet animals "$sound"
cow
Примечание: declare
нельзя поместить в функцию. Любое использование declare
внутри функции bash переводит создаваемую им переменную local в область действия этой функции, что означает, что мы не можем получить доступ или изменить глобальные массивы с ее помощью. (В bash 4 вы можете использовать declare -g для объявления глобальных переменных - но в bash 4 вы можете в первую очередь использовать ассоциативные массивы, избегая этого обходного пути.)
Резюме:
объявить -A
для ассоциативных массивов. объявить
, если вы не можете выполнить обновление. awk
и вообще избегайте проблемы. hput () {
eval hash"$1"='$2'
}
hget () {
eval echo '${hash'"$1"'#hash}'
}
hput France Paris
hput Netherlands Amsterdam
hput Spain Madrid
echo `hget France` and `hget Netherlands` and `hget Spain`
$ sh hash.sh
Paris and Amsterdam and Madrid
Вы можете дополнительно изменить интерфейс hput () / hget (), чтобы вы назвали хеши следующим образом:
hput() {
eval "$1""$2"='$3'
}
hget() {
eval echo '${'"$1$2"'#hash}'
}
, а затем
hput capitals France Paris
hput capitals Netherlands Amsterdam
hput capitals Spain Madrid
echo `hget capitals France` and `hget capitals Netherlands` and `hget capitals Spain`
Это позволяет вы определяете другие карты, которые не конфликтуют (например, 'rcapitals', который выполняет поиск страны по столице). Но в любом случае, я думаю, вы обнаружите, что все это довольно ужасно с точки зрения производительности.
Если вам действительно нужен быстрый поиск хэша, есть ужасный, ужасный прием, который действительно работает очень хорошо. Это так: запишите свои ключи / значения во временный файл, по одному на строку, затем используйте 'grep "^ $ key"', чтобы вывести их, используя каналы с cut, awk или sed или что-то еще, чтобы получить значения.
Как я уже сказал, это звучит ужасно, и похоже, что он должен быть медленным и выполнять всевозможные ненужные операции ввода-вывода, но на практике это очень быстро (кеш-диск - это круто, не так ли?), Даже для очень большие хеш-таблицы. Вы должны сами обеспечить уникальность ключа и т. Д. Даже если у вас всего несколько сотен записей, комбинация выходной файл / grep будет немного быстрее - по моему опыту, в несколько раз быстрее. К тому же память съедает меньше.
Вот один из способов сделать это:
hinit() {
rm -f /tmp/hashmap.$1
}
hput() {
echo "$2 $3" >> /tmp/hashmap.$1
}
hget() {
grep "^$2 " /tmp/hashmap.$1 | awk '{ print $2 };'
}
hinit capitals
hput capitals France Paris
hput capitals Netherlands Amsterdam
hput capitals Spain Madrid
echo `hget capitals France` and `hget capitals Netherlands` and `hget capitals Spain`
До bash 4 не было хорошего способа использовать ассоциативные массивы в bash. Лучше всего использовать интерпретируемый язык, который действительно поддерживает такие вещи, как awk. С другой стороны, bash 4 их поддерживает .
Что касается less хороших способов в bash 3, вот ссылка, которая может помочь: http://mywiki.wooledge.org/BashFAQ/006
Две вещи: вы можете использовать память вместо / tmp в любом ядре 2.6, используя / dev / shm (Redhat), другие дистрибутивы могут отличаться. Также hget может быть повторно реализован с помощью read следующим образом:
function hget {
while read key idx
do
if [ $key = $2 ]
then
echo $idx
return
fi
done < /dev/shm/hashmap.$1
}
Кроме того, предполагая, что все ключи уникальны, return замыкает цикл чтения и предотвращает необходимость чтения всех записей. Если в вашей реализации могут быть повторяющиеся ключи, просто не учитывайте return. Это экономит затраты на чтение и разветвление как grep, так и awk. Использование / dev / shm для обеих реализаций дало следующее: time hget для хэша из 3 записей, ищущего последнюю запись:
Grep / Awk:
hget() {
grep "^$2 " /dev/shm/hashmap.$1 | awk '{ print $2 };'
}
$ time echo $(hget FD oracle)
3
real 0m0.011s
user 0m0.002s
sys 0m0.013s
Read / echo:
$ time echo $(hget FD oracle)
3
real 0m0.004s
user 0m0.000s
sys 0m0.004s
при многократных вызовах я никогда не видел меньше, чем улучшение на 50%.
Все это можно отнести к разветвленной работе из-за использования / dev / shm
.