Tablice asocjacyjne w skryptach powłoki

Potrzebowaliśmy skryptu, który symuluje Tablice asocjacyjne lub mapę podobną do struktury danych do skryptów powłoki, dowolnego ciała?

Author: Sridhar Ratnakumar, 2009-03-27

17 answers

Aby dodać do odpowiedź Irfana , Oto krótsza i szybsza wersja get(), ponieważ nie wymaga iteracji nad treścią Mapy:

get() {
    mapName=$1; key=$2

    map=${!mapName}
    value="$(echo $map |sed -e "s/.*--${key}=\([^ ]*\).*/\1/" -e 's/:SP:/ /g' )"
}
 21
Author: Jerry Penner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:12

Inną opcją, jeśli przenośność nie jest twoim głównym problemem, jest użycie tablic asocjacyjnych wbudowanych w powłokę. To powinno działać w bash 4.0 (dostępne teraz na większości głównych dystrybucji, ale nie na OS X, chyba że zainstalujesz go samodzielnie), ksh i zsh:

declare -A newmap
newmap[name]="Irfan Zulfiqar"
newmap[designation]=SSE
newmap[company]="My Own Company"

echo ${newmap[company]}
echo ${newmap[name]}

W zależności od powłoki, może być konieczne wykonanie typeset -A newmap zamiast declare -A newmap, lub w niektórych może to nie być wcale konieczne.

 123
Author: Brian Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-28 15:15:29

Inny sposób bez bash 4.

#!/bin/bash

# A pretend Python dictionary with bash 3 
ARRAY=( "cow:moo"
        "dinosaur:roar"
        "bird:chirp"
        "bash:rock" )

for animal in "${ARRAY[@]}" ; do
    KEY=${animal%%:*}
    VALUE=${animal#*:}
    printf "%s likes to %s.\n" "$KEY" "$VALUE"
done

echo -e "${ARRAY[1]%%:*} is an extinct animal which likes to ${ARRAY[1]#*:}\n"

Możesz też wrzucić tam oświadczenie if za przeszukanie. if [[$var = ~ / blah/]]. albo cokolwiek.

 83
Author: Bubnoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-15 17:21:12

Myślę, że musisz się cofnąć i pomyśleć o tym, czym naprawdę jest mapa lub tablica asocjacyjna. Wszystko to jest sposób, aby zapisać wartość dla danego klucza i odzyskać tę wartość szybko i skutecznie. Możesz również chcieć mieć możliwość iteracji nad kluczami, aby pobrać każdą parę wartości klucza lub usunąć klucze i powiązane z nimi wartości.

Teraz pomyśl o strukturze danych, której używasz cały czas w skryptach powłoki, a nawet tylko w powłoce bez pisania skryptu, która ma te właściwości. Zakłopotany? To system plików.

Naprawdę, wszystko, czego potrzebujesz, aby mieć tablicę asocjacyjną w programowaniu powłoki, to katalog tymczasowy. mktemp -d jest konstruktorem tablicy asocjacyjnej:

prefix=$(basename -- "$0")
map=$(mktemp -dt ${prefix})
echo >${map}/key somevalue
value=$(cat ${map}/key)

Jeśli nie masz ochoty używać echo i cat, zawsze możesz napisać kilka małych wrapperów; te są wzorowane na Irfanach, chociaż po prostu wypisują wartość zamiast ustawiać dowolne zmienne, takie jak $value:

#!/bin/sh

prefix=$(basename -- "$0")
mapdir=$(mktemp -dt ${prefix})
trap 'rm -r ${mapdir}' EXIT

put() {
  [ "$#" != 3 ] && exit 1
  mapname=$1; key=$2; value=$3
  [ -d "${mapdir}/${mapname}" ] || mkdir "${mapdir}/${mapname}"
  echo $value >"${mapdir}/${mapname}/${key}"
}

get() {
  [ "$#" != 2 ] && exit 1
  mapname=$1; key=$2
  cat "${mapdir}/${mapname}/${key}"
}

put "newMap" "name" "Irfan Zulfiqar"
put "newMap" "designation" "SSE"
put "newMap" "company" "My Own Company"

value=$(get "newMap" "company")
echo $value

value=$(get "newMap" "name")
echo $value

Edit: takie podejście jest rzeczywiście dość nieco szybsze niż wyszukiwanie liniowe przy użyciu sed sugerowanego przez pytającego, a także bardziej wytrzymałe(pozwala na to, aby klucze i wartości zawierały -,=, spację, qnd": SP:"). Fakt, że korzysta on z systemu plików, nie czyni go wolnym; pliki te nigdy nie są gwarantowane, że zostaną zapisane na dysku, chyba że wywołasz sync; dla plików tymczasowych, takich jak ten o krótkim czasie życia, nie jest mało prawdopodobne, że wiele z nich nigdy nie zostanie zapisanych na dysku.

Zrobiłem kilka benchmarków kodu Irfana, Jerry ' ego modyfikacja kodu Irfana i mojego kodu za pomocą następującego programu sterownika:

#!/bin/sh

mapimpl=$1
numkeys=$2
numvals=$3

. ./${mapimpl}.sh    #/ <- fix broken stack overflow syntax highlighting

for (( i = 0 ; $i < $numkeys ; i += 1 ))
do
    for (( j = 0 ; $j < $numvals ; j += 1 ))
    do
        put "newMap" "key$i" "value$j"
        get "newMap" "key$i"
    done
done

Wyniki:

    $ time ./driver.sh irfan 10 5

    real    0m0.975s
    user    0m0.280s
    sys     0m0.691s

    $ time ./driver.sh brian 10 5

    real    0m0.226s
    user    0m0.057s
    sys     0m0.123s

    $ time ./driver.sh jerry 10 5

    real    0m0.706s
    user    0m0.228s
    sys     0m0.530s

    $ time ./driver.sh irfan 100 5

    real    0m10.633s
    user    0m4.366s
    sys     0m7.127s

    $ time ./driver.sh brian 100 5

    real    0m1.682s
    user    0m0.546s
    sys     0m1.082s

    $ time ./driver.sh jerry 100 5

    real    0m9.315s
    user    0m4.565s
    sys     0m5.446s

    $ time ./driver.sh irfan 10 500

    real    1m46.197s
    user    0m44.869s
    sys     1m12.282s

    $ time ./driver.sh brian 10 500

    real    0m16.003s
    user    0m5.135s
    sys     0m10.396s

    $ time ./driver.sh jerry 10 500

    real    1m24.414s
    user    0m39.696s
    sys     0m54.834s

    $ time ./driver.sh irfan 1000 5

    real    4m25.145s
    user    3m17.286s
    sys     1m21.490s

    $ time ./driver.sh brian 1000 5

    real    0m19.442s
    user    0m5.287s
    sys     0m10.751s

    $ time ./driver.sh jerry 1000 5

    real    5m29.136s
    user    4m48.926s
    sys     0m59.336s

 31
Author: Brian Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-02 19:33:58
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
 14
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-30 00:12:16
####################################################################
# Bash v3 does not support associative arrays
# and we cannot use ksh since all generic scripts are on bash
# Usage: map_put map_name key value
#
function map_put
{
    alias "${1}$2"="$3"
}

# map_get map_name key
# @return value
#
function map_get
{
    alias "${1}$2" | awk -F"'" '{ print $2; }'
}

# map_keys map_name 
# @return map keys
#
function map_keys
{
    alias -p | grep $1 | cut -d'=' -f1 | awk -F"$1" '{print $2; }'
}

Przykład:

mapName=$(basename $0)_map_
map_put $mapName "name" "Irfan Zulfiqar"
map_put $mapName "designation" "SSE"

for key in $(map_keys $mapName)
do
    echo "$key = $(map_get $mapName $key)
done
 7
Author: Vadim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-28 15:28:24

Bash4 wspiera to natywnie. Nie używaj grep LUB eval, są najbrzydszymi hackami.

Aby uzyskać szczegółową odpowiedź z przykładowym kodem zobacz: https://stackoverflow.com/questions/3467959

 5
Author: lhunath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:50

Teraz odpowiadam na to pytanie.

Następujące Skrypty symulują tablice asocjacyjne w skryptach powłoki. To proste i bardzo łatwe do zrozumienia.

Map to nic innego jak niekończący się ciąg znaków, który ma keyValuePair zapisany jako --name = Irfan --design=SSE --company=My: SP: Own:SP: Company

Spacje zastępuje się": SP: "dla wartości

put() {
    if [ "$#" != 3 ]; then exit 1; fi
    mapName=$1; key=$2; value=`echo $3 | sed -e "s/ /:SP:/g"`
    eval map="\"\$$mapName\""
    map="`echo "$map" | sed -e "s/--$key=[^ ]*//g"` --$key=$value"
    eval $mapName="\"$map\""
}

get() {
    mapName=$1; key=$2; valueFound="false"

    eval map=\$$mapName

    for keyValuePair in ${map};
    do
        case "$keyValuePair" in
            --$key=*) value=`echo "$keyValuePair" | sed -e 's/^[^=]*=//'`
                      valueFound="true"
        esac
        if [ "$valueFound" == "true" ]; then break; fi
    done
    value=`echo $value | sed -e "s/:SP:/ /g"`
}

put "newMap" "name" "Irfan Zulfiqar"
put "newMap" "designation" "SSE"
put "newMap" "company" "My Own Company"

get "newMap" "company"
echo $value

get "newMap" "name"
echo $value

Edit: dodałem kolejną metodę do pobrania wszystkich kluczy.

getKeySet() {
    if [ "$#" != 1 ]; 
    then 
        exit 1; 
    fi

    mapName=$1; 

    eval map="\"\$$mapName\""

    keySet=`
           echo $map | 
           sed -e "s/=[^ ]*//g" -e "s/\([ ]*\)--/\1/g"
          `
}
 3
Author: Irfan Zulfiqar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-14 08:11:06

Dla Bash 3, jest szczególny przypadek, który ma ładne i proste rozwiązanie:

Jeśli nie chcesz obsługiwać wielu zmiennych lub klucze są po prostu nieprawidłowymi identyfikatorami zmiennych, i Twoja tablica ma gwarancję, że będzie miała mniej niż 256 pozycji , możesz nadużywać wartości zwracanych przez funkcję. Rozwiązanie to nie wymaga żadnej podshell, ponieważ wartość jest łatwo dostępna jako zmienna, ani żadnej iteracji, tak aby wydajność krzyczała. Również jest bardzo czytelny, prawie jak Bash 4 wersja.

Oto najbardziej podstawowa wersja:

hash_index() {
    case $1 in
        'foo') return 0;;
        'bar') return 1;;
        'baz') return 2;;
    esac
}

hash_vals=("foo_val"
           "bar_val"
           "baz_val");

hash_index "foo"
echo ${hash_vals[$?]}

Pamiętaj, używaj pojedynczych cudzysłowów w case, w przeciwnym razie podlega globbingowi. Naprawdę przydatne dla statycznych / zamrożonych hashów od samego początku, ale można napisać generator indeksów z tablicy hash_keys=().

Uważaj, domyślnie jest to pierwsza, więc możesz chcieć odstawić element zerowy:

hash_index() {
    case $1 in
        'foo') return 1;;
        'bar') return 2;;
        'baz') return 3;;
    esac
}

hash_vals=("",           # sort of like returning null/nil for a non existent key
           "foo_val"
           "bar_val"
           "baz_val");

hash_index "foo" || echo ${hash_vals[$?]}  # It can't get more readable than this

Zastrzeżenie: długość jest teraz Niepoprawna.

Alternatywnie, jeśli chcesz zachować indeksowanie oparte na 0, możesz zarezerwować inny wartość indeksu i Ochrona przed nieistniejącym kluczem, ale jest mniej czytelny:

hash_index() {
    case $1 in
        'foo') return 0;;
        'bar') return 1;;
        'baz') return 2;;
        *)   return 255;;
    esac
}

hash_vals=("foo_val"
           "bar_val"
           "baz_val");

hash_index "foo"
[[ $? -ne 255 ]] && echo ${hash_vals[$?]}

Lub, aby długość była prawidłowa, przesunięcie indeksu o jeden:

hash_index() {
    case $1 in
        'foo') return 1;;
        'bar') return 2;;
        'baz') return 3;;
    esac
}

hash_vals=("foo_val"
           "bar_val"
           "baz_val");

hash_index "foo" || echo ${hash_vals[$(($? - 1))]}
 2
Author: Lloeki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-03 16:15:01

Możesz używać dynamicznych nazw zmiennych i pozwolić, aby nazwy zmiennych działały jak klucze hashmapy.

Na przykład, jeśli Masz plik wejściowy z dwoma kolumnami, nazwa, kredyt, jak w poniższym przykładzie, i chcesz zsumować dochód każdego użytkownika:

Mary 100
John 200
Mary 50
John 300
Paul 100
Paul 400
David 100

Komenda poniżej podsumuje wszystko, używając zmiennych dynamicznych jako kluczy, w postaci map_${person}:

while read -r person money; ((map_$person+=$money)); done < <(cat INCOME_REPORT.log)

Aby przeczytać wyniki:

set | grep map

Wyjście będzie:

map_David=100
map_John=500
map_Mary=150
map_Paul=500

Te techniki, rozwijam na Githubie funkcję, która działa tak samo jak obiekt HashMap, shell_map .

W celu utworzenia instancji " HashMap" funkcja shell_map jest w stanie tworzyć swoje kopie pod różnymi nazwami. Każda nowa kopia funkcji będzie miała inną zmienną $FUNCNAME. $FUNCNAME jest następnie używane do tworzenia przestrzeni nazw dla każdej instancji Mapy.

Klucze map są zmiennymi globalnymi, w postaci $FUNCNAME_DATA_ $ KEY, gdzie $KEY jest kluczem dodanym do mapy. Zmienne te są zmiennymi dynamicznymi .

Poniżej podam jego uproszczoną wersję, abyś mógł użyć jej jako przykładu.

#!/bin/bash

shell_map () {
    local METHOD="$1"

    case $METHOD in
    new)
        local NEW_MAP="$2"

        # loads shell_map function declaration
        test -n "$(declare -f shell_map)" || return

        # declares in the Global Scope a copy of shell_map, under a new name.
        eval "${_/shell_map/$2}"
    ;;
    put)
        local KEY="$2"  
        local VALUE="$3"

        # declares a variable in the global scope
        eval ${FUNCNAME}_DATA_${KEY}='$VALUE'
    ;;
    get)
        local KEY="$2"
        local VALUE="${FUNCNAME}_DATA_${KEY}"
        echo "${!VALUE}"
    ;;
    keys)
        declare | grep -Po "(?<=${FUNCNAME}_DATA_)\w+((?=\=))"
    ;;
    name)
        echo $FUNCNAME
    ;;
    contains_key)
        local KEY="$2"
        compgen -v ${FUNCNAME}_DATA_${KEY} > /dev/null && return 0 || return 1
    ;;
    clear_all)
        while read var; do  
            unset $var
        done < <(compgen -v ${FUNCNAME}_DATA_)
    ;;
    remove)
        local KEY="$2"
        unset ${FUNCNAME}_DATA_${KEY}
    ;;
    size)
        compgen -v ${FUNCNAME}_DATA_${KEY} | wc -l
    ;;
    *)
        echo "unsupported operation '$1'."
        return 1
    ;;
    esac
}

Użycie:

shell_map new credit
credit put Mary 100
credit put John 200
for customer in `credit keys`; do 
    value=`credit get $customer`       
    echo "customer $customer has $value"
done
credit contains_key "Mary" && echo "Mary has credit!"
 2
Author: Bruno Negrão Zica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-04 16:51:32

Uznałem, że prawdą jest, jak już wspomniano, że najlepszą metodą jest zapisanie key / vals do pliku, a następnie użycie grep/awk do ich pobrania. Brzmi to jak wszelkiego rodzaju niepotrzebne IO, ale pamięć podręczna dysku działa i sprawia, że jest niezwykle wydajna-znacznie szybciej niż próba przechowywania ich w pamięci za pomocą jednej z powyższych metod (jak pokazują benchmarki).

Oto szybka, czysta metoda, którą lubię:

hinit() {
    rm -f /tmp/hashmap.$1
}

hput() {
    echo "$2 $3" >> /tmp/hashmap.$1
}

hget() {
    grep "^$2 " /tmp/hashmap.$1 | awk '{ print $2 };'
}

hinit capitols
hput capitols France Paris
hput capitols Netherlands Amsterdam
hput capitols Spain Madrid

echo `hget capitols France` and `hget capitols Netherlands` and `hget capitols Spain`

Jeśli chcesz wymusić pojedynczą wartość na klucz, możesz również wykonać mała akcja grep/sed w hput ().

 1
Author: Al P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-09 17:19:59

Jaka szkoda, że wcześniej nie widziałem pytania-napisałem bibliotekę shell-framework , która zawiera m.in. mapy (tablice asocjacyjne). Ostatnią jego wersję można znaleźć tutaj .

Przykład:

#!/bin/bash 
#include map library
shF_PATH_TO_LIB="/usr/lib/shell-framework"
source "${shF_PATH_TO_LIB}/map"

#simple example get/put
putMapValue "mapName" "mapKey1" "map Value 2"
echo "mapName[mapKey1]: $(getMapValue "mapName" "mapKey1")"

#redefine old value to new
putMapValue "mapName" "mapKey1" "map Value 1"
echo "after change mapName[mapKey1]: $(getMapValue "mapName" "mapKey1")"

#add two new pairs key/values and print all keys
putMapValue "mapName" "mapKey2" "map Value 2"
putMapValue "mapName" "mapKey3" "map Value 3"
echo -e "mapName keys are \n$(getMapKeys "mapName")"

#create new map
putMapValue "subMapName" "subMapKey1" "sub map Value 1"
putMapValue "subMapName" "subMapKey2" "sub map Value 2"

#and put it in mapName under key "mapKey4"
putMapValue "mapName" "mapKey4" "subMapName"

#check if under two key were placed maps
echo "is map mapName[mapKey3]? - $(if isMap "$(getMapValue "mapName" "mapKey3")" ; then echo Yes; else echo No; fi)"
echo "is map mapName[mapKey4]? - $(if isMap "$(getMapValue "mapName" "mapKey4")" ; then echo Yes; else echo No; fi)"

#print map with sub maps
printf "%s\n" "$(mapToString "mapName")"
 1
Author: Beggy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-03 09:08:32

Shell nie ma wbudowanej mapy jak struktura danych, używam raw string do opisywania takich elementów:

ARRAY=(
    "item_A|attr1|attr2|attr3"
    "item_B|attr1|attr2|attr3"
    "..."
)

Gdy wyodrębnia elementy i ich atrybuty:

for item in "${ARRAY[@]}"
do
    item_name=$(echo "${item}"|awk -F "|" '{print $1}')
    item_attr1=$(echo "${item}"|awk -F "|" '{print $2}')
    item_attr2=$(echo "${item}"|awk -F "|" '{print $3}')

    echo "${item_name}"
    echo "${item_attr1}"
    echo "${item_attr2}"
done
To wydaje się nie mądre niż odpowiedź innych ludzi, ale łatwe do zrozumienia dla nowych ludzi do skorupy.
 1
Author: coanor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-05 08:38:09

Zmodyfikowałem rozwiązanie Wadima następująco:

####################################################################
# Bash v3 does not support associative arrays
# and we cannot use ksh since all generic scripts are on bash
# Usage: map_put map_name key value
#
function map_put
{
    alias "${1}$2"="$3"
}

# map_get map_name key
# @return value
#
function map_get {
    if type -p "${1}$2"
        then
            alias "${1}$2" | awk -F "'" '{ print $2; }';
    fi
}

# map_keys map_name 
# @return map keys
#
function map_keys
{
    alias -p | grep $1 | cut -d'=' -f1 | awk -F"$1" '{print $2; }'
}

Zmiana polega na map_get, aby zapobiec zwracaniu błędów, jeśli poprosisz o klucz, który nie istnieje, chociaż efektem ubocznym jest to, że będzie on również po cichu ignorował brakujące mapy, ale lepiej pasował do mojego przypadku użycia, ponieważ chciałem tylko sprawdzić klucz, aby pominąć elementy w pętli.

 0
Author: Haravikk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-11 14:22:16

Kilka lat temu napisałem bibliotekę skryptów dla Basha, która obsługiwała tablice asocjacyjne między innymi (logowanie, pliki konfiguracyjne, rozszerzone wsparcie dla argumentów linii poleceń, generowanie pomocy, Testowanie jednostek, itp.). Biblioteka zawiera wrapper dla tablic asocjacyjnych i automatycznie przełącza się na odpowiedni model (wewnętrzny dla bash4 i emulować dla poprzednich wersji). Został nazwany shell-framework i hostowany w origo.ethz.ch ale dziś zasób jest zamknięty. Jeśli ktoś jeszcze tego potrzebuje Mogę się tym z Tobą podzielić.

 0
Author: Beggy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-13 12:38:12

Późna odpowiedź, ale rozważ rozwiązanie problemu w ten sposób, używając wbudowanego w bash read , Jak pokazano w poniższym fragmencie kodu ze skryptu zapory ufw. To podejście ma tę zaletę, że używa się tak wielu rozdzielonych zestawów pól (nie tylko 2), Jak jest to pożądane. Wykorzystaliśmy | delimiter, ponieważ specyfikatory zakresu portów mogą wymagać dwukropka, czyli 6001:6010.

#!/usr/bin/env bash

readonly connections=(       
                            '192.168.1.4/24|tcp|22'
                            '192.168.1.4/24|tcp|53'
                            '192.168.1.4/24|tcp|80'
                            '192.168.1.4/24|tcp|139'
                            '192.168.1.4/24|tcp|443'
                            '192.168.1.4/24|tcp|445'
                            '192.168.1.4/24|tcp|631'
                            '192.168.1.4/24|tcp|5901'
                            '192.168.1.4/24|tcp|6566'
)

function set_connections(){
    local range proto port
    for fields in ${connections[@]}
    do
            IFS=$'|' read -r range proto port <<< "$fields"
            ufw allow from "$range" proto "$proto" to any port "$port"
    done
}

set_connections
 0
Author: AsymLabs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-15 16:58:41

Dodanie innej opcji, jeśli jq jest dostępny:

export NAMES="{
  \"Mary\":\"100\",
  \"John\":\"200\",
  \"Mary\":\"50\",
  \"John\":\"300\",
  \"Paul\":\"100\",
  \"Paul\":\"400\",
  \"David\":\"100\"
}"
export NAME=David
echo $NAMES | jq --arg v "$NAME" '.[$v]' | tr -d '"' 
 0
Author: critium,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 20:11:25