Нарезать массив с пробелами в bash - PullRequest
0 голосов
/ 19 февраля 2020

Я хочу использовать хранилище значений ключей в bash, а затем обращаться к элементам и работать с ними. Пока у меня есть следующий код, который находит ключ в хранилище, но не может извлечь значения из массива без интерпретации пробелов.

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

# the array is a key: value storage, the keys do not contain spaces, but the values might
# there are always three values for each key, but the number of words in them is unknown
services=("key1" "some values" "another_value" "a lot of values"
          "key2" "other values" "simple_value2" "a lot of values here"
          "key3" "something else here" "another_value3" "whatever")

# this should look for the given value in the array and return the key and respective values if its found
function find_key () {
    arr=("${@:2}")
    len=$(( ${#arr[@]} -1 ))
    for i in $(seq 0 4 "$len")
    do
    if [[ ${arr[$i]} == "$1" ]] ; then
        # this should get the i'th element and 4 following elements (the values), which works correctly
        result="${arr[*]:$i:4}"
        # at this point result is just a regular array and there is no way to separate the values again

        # this prints just one line with all words
        for x in "${result[@]}"; do
            echo "element: '$x'"
        done

        # I want to return the array ("key" "value 1" "value 2" "the third value") from here to work with it later
        echo "${result[@]}"
        return 0
    fi
    done
    return 1
}

key_and_values="$(find_key "key2" "${services[@]}")"
echo "${key_and_values[@]}"

Вывод:

element: 'key2 other values simple_value2 a lot of values here'
key2 other values simple_value2 a lot of values here

И я ищу:

element: 'key2'
element: 'other values'
element: 'simple_value2'
element: 'a lot of values here'
key2 other values simple_value2 a lot of values here

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Измените:

result="${arr[*]:$i:4}"

на массив:

result=("${arr[@]:$i:4}")

Есть некоторые проблемы с вашим скриптом:

  • "${key_and_values[@]}" - key_and_values это не массив, это обычная переменная.
  • echo "${result[@]}" будет работать ненормально, например, result[0]='-n'. Используйте printf "%s\n" "${result[@]}" | paste -sd ' ' или подобное.

Я думаю, я бы go с чем-то вместе:

find_key() {
    arr=("${@:2}")
    for ((i=0; i < ${#arr[@]}; i+=4)); do
        if [[ ${arr[$i]} == "$1" ]] ; then
            printf "%s\0" "${arr[@]:$i:4}"
            return 0
        fi
    done
    return 1
}

readarray -d '' -t key_and_values < <(find_key "key2" "${services[@]}")
printf "element: %s\n" "${key_and_values[@]}"
printf "%s\n" "${key_and_values[@]}" | paste -sd' '
0 голосов
/ 19 февраля 2020

Я использую этот техник в piu-piu

array=("abs 123 ---" "DEF 456 +++")
for items in "${array[@]}"; {
    sub=( $items )
    echo  ======
    for item in ${sub[@]}; {
        echo $item
    }
}

вывод

======
abs
123
---
======
DEF
456
+++

Также вы можете использовать ассоциативный массив и l oop над индексами

declare -A items=( [item1]="123 abc" [item2]="dfe 234" )

for key in ${!items[@]}; {
    echo "key=$key"
    echo "val=${items[$key]}"
}

output

key=item2
val=dfe 234
key=item1
val=123 abc

Но вопрос был о срезании, верно?), Конечно, вы можете нарезать массив следующим образом

array=("abs 123" "DEF 456" "ASA 789")

$ echo "${array[@]:1}"
DEF 456 ASA 789

$ echo "${array[@]::1}"
abs 123

$ echo "${array[@]:1:3}"
DEF 456 ASA 789

$ echo "${array[@]:1:1}"
DEF 456
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...