it-swarm.com.ru

Преобразовать текстовую строку в bash в массив

Как мне преобразовать такую ​​строку в BASH в массив в bash!

У меня есть строка str , которая содержит "title1 title2 title3 title4 title5" (Разделенные пробелами заголовки)

Я хочу, чтобы str был изменен на массив, который будет хранить каждый заголовок в каждом индексе. 

11
Ayush Mishra

Чтобы преобразовать строку в массив, скажите:

$ str="title1 title2 title3 title4 title5"
$ arr=( $str )

Оболочка будет выполнять разбиение Word на пробелы, если вы не заключите строку в кавычки.

Чтобы зациклить элементы в созданном таким образом массиве:

$ for i in "${arr[@]}"; do echo $i; done
title1
title2
title3
title4
title5
26
devnull

Другой метод, использующий чтение:

read -a array <<< $str
1
perreal

Я нахожусь в плачевном положении, когда у меня есть давний скрипт Shell, который обновляется с внутреннего использования скалярных переменных до использования массивов. Но , пользователям также разрешается устанавливать эти переменные самостоятельно, по желанию, с помощью файла, получаемого при запуске.

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

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

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

convert_array() {
        __array_name="$1"; shift
        __declaration="$(declare -p "$__array_name" 2>/dev/null)"
        if [ -z "${__declaration}" ]; then
                # variable is not set
                eval "${__array_name}=()"
        Elif [ "$(echo "${__declaration}" | grep -c '^declare \-a')" -eq 0 ]; then
                # variable is not an array
                __existing_value="$(eval echo "\${$__array_name}" | sed -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,')"
                unset "${__array_name?}"
                IFS=" " read -r -a "${__array_name?}" <<< "${__existing_value}"
        fi
}

Он чисто обрабатывает все случаи: существующую переменную, существующий массив и не задавать вообще.

Также обратите внимание, что хотя это может показаться излишним:

__existing_value="$(eval echo "\${$__array_name}" | sed -e 's,^[[:space:]]*,,' -e 's,[[:space:]]*$,,')"

... он обрабатывает случай, когда большинство людей создают свои исходные конфигурации примерно так:

ADDITIONAL_OPTIONS="${ADDITIONAL_OPTIONS} -Xmx2g"
ADDITIONAL_OPTIONS="${ADDITIONAL_OPTIONS} -Dsome.property=foo"

В этих случаях переменная $ADDITIONAL_OPTIONS будет начинаться с пробела. Если вы знаете, что ваши входы не будут нуждаться в обрезке, этот бит не нужен.

test_foo() {
        convert_array FOO
        for VAR in "${FOO[@]}"; do
                echo "var=$VAR"
        done
}

$ FOO="foo bar baz"
$ test_foo
var=foo
var=bar
var=baz
$ unset FOO
$ test_foo
$ FOO=(foo bar baz "something with spaces")
$ test_foo
var=foo
var=bar
var=baz
var=something with spaces
0
Benjamin Reed