LINUX.ORG.RU

Как передать массив имен переменных и дополнительно аргументы?

 


0

2

Есть какой-то более элегантный способ работы с аргументами в функции?

z1() {
    local local_array=("${@}")
    for i in $(seq 1 ${local_array[0]}); do
        local "${local_array[${i}]}"="${local_array[(("${i}"+local_array[0]))]}";shift
    done
    echo "${x}" "${y}" "${z}"
}


x=1
y=2
z=3
VARIABLES=("x" "y")

z1 "${#VARIABLES[@]}" \
   "${VARIABLES[@]}" \
   "${x}" \
   "${y}" \
   "${z}"
★★★★

Последнее исправление: serg002 (всего исправлений: 3)
Ответ на: комментарий от sin_a

Давай пример. А то я это всё понял так: объявляй глобальные переменные и внутри функции их используй

serg002 ★★★★
() автор топика
Последнее исправление: serg002 (всего исправлений: 1)

Какой ужас. Если бы я не видел в удалённых про yaml я бы подумал, что ты сошёл с ума. Впрочем, всё равно плохо. Это баш, его не испортить использованием глобальных переменных. А вот простынёй нечитаемого жонглирования массивами - можно.

PS Я за бан. ТС намеренно неполно доносит решаемую задачу.

legolegs ★★★★★
()
Ответ на: комментарий от serg002

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

masa ★★
()
Последнее исправление: masa (всего исправлений: 1)
Ответ на: комментарий от serg002

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

masa ★★
()
Ответ на: комментарий от serg002

Во-первых, шелл нужен для того, чтобы файлы двигать и программы запускать, а не парсить текст или делать сложную логику. Функции в дружелюбных шел-скриптах должны принимать немного тривиальных аргументов, или много одинаковых типа delete_n_first_lines 5 file1 file2 file3. Такая функция пишется и читается очень легко.

А во-вторых, если уж так сильно хочется сложные функкции и не запутаться в портянках, то я последний раз делал так (реальный код):

function get_battle_index()
{
    local usage='Usage: .. chapter piece'
    local chapter=${1:?$usage}
    local piece=${2:?$usage}
    for ((index=0;index<${#DATATABLE[@]}/8;++index)); do
        if [ "${DATATABLE[0+index*8]}" -eq "$chapter" ] && [ "${DATATABLE[1+index*8]}" -eq "$piece" ]; then
            echo $index
            return
        fi
    done
    return 1
}

И да, DATATABLE глобальная.

legolegs ★★★★★
()
Ответ на: комментарий от serg002

Плохой для других языков, на для bash вполне хороший. Приватные можно по номеру:

# не помню точно как, но примерно
local pVar_a="$4"
local pVar_normalnoename4tobybiloponyatno4toetotakoe="$6"
bcon
()
Последнее исправление: bcon (всего исправлений: 1)
Ответ на: комментарий от serg002

Если тебе не нравится использовать для каждой функции F переменные F_OPT_1 … F_OPT_N, то ты можешь использовать одну переменную F_OPT, значением которой сделать массив опций. Правда в этом случае тебе придётся держать в уме количество параметров и их порядок.

Кстати, раз уж ты всё равно держишь в уме количество параметров то можешь всё передавать в массиве позиционных переменных, отсчитав из них сколько нужно.

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

А, можно поступить и по другому, можно в первой позиционной переменной передавать число опций. В остальном это предыдущий случай.

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

sin_a ★★★★★
()
Ответ на: комментарий от masa

В Памплоне есть модули для синглтонизации состояния

То что фОнаты наворачивают через классы инкапсуляцию части глобального состояния - лингва франка проходимцев из всяких жаб

qulinxao3 ★☆
()

Как передать массив имен переменных и дополнительно аргументы?

Что бы передать массив имён переменных передавай их в конце как отдельные аргументы, после дополнительных аргументов.

anonymous
()
Ответ на: комментарий от kaldeon
run() {
	local arr=("${!1}")

        for x in $(seq 0 "${#arr[@]}"); do
        echo "${arr[${x}]}"

        # как правильно пройтись по аргументам типа $1, $2, чтобы сформировать переменные типа
        local "${arr[${x}]}"="${1}" # первая итерация
        local "${arr[${x}]}"="${2}" # первая итерация
        echo "${((x))}" # <-- вот тут проблема использовать x как индекс
    done

}

z2() {
    local x=1
    local y=2
    local z=3
    arr=(x y z)

    run 'arr[@]' \
        "${x}" \
        "${y}" \
        "${z}"
}

z2
serg002 ★★★★
() автор топика
Последнее исправление: serg002 (всего исправлений: 1)
Ответ на: комментарий от LongLiveUbuntu

Эти секретные знания звучат как «как превратить позиционные аргументы передаваемые в функцию в именованные» и в шапке топика это явно видно

serg002 ★★★★
() автор топика
Последнее исправление: serg002 (всего исправлений: 2)
Ответ на: комментарий от serg002

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

def foo(bar):
    print(bar) # Идентификатор 'hurr' никак не передаётся

hurr=123
foo(hurr)

Но в баше она как раз решается через глобальные переменные.

FOO=4
BAR=6
BAZ=(all your base are belong to us)
function hurr() {
    printf '%s=%s\n' $1 ${!1}
    printf '%s=%s\n' $2 ${!2}
    array_ref=${3}[@]
    printf '%s=' $3
    printf '%s ' "${!array_ref}"
    printf '\n'
}
hurr FOO BAR BAZ
legolegs ★★★★★
()
Ответ на: комментарий от legolegs

UPD: есть ещё один способ. Он буквально передаёт переменную вместе с именем и про него все знают хотя немногие, думаю, пользовались им с функциями:

function hurr() {
    set | grep '^xx[0-9a-zA-Z_]*='
    printf 'xxFOO=%s xxBAR=%s\n' "$xxFOO" "$xxBAR"
    printf 'xxBAZ='
    printf '[%s] ' ${xxBAZ[@]}
    printf '\n'
}
xxFOO=44 xxBAR=66 xxBAZ=(массивы так передать нельзя) hurr
legolegs ★★★★★
()

Есть какой-то более элегантный способ работы с аргументами в функции?

Да, использовать более подходящий язык.

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

firkax ★★★★★
()