2016-07-27 2 views
2

Я хотел бы изменить аргументы функции перед передачей их следующей функции.Изменить аргументы функции в Bash

firstfunction() { 
    # change "-f" to "--format" in arguments 
    secondfunction "[email protected]" 
} 

Я попытался преобразовать в массив, изменить массив и преобразовать обратно в аргументы. Но это выглядит так сложно. Можно ли сделать это проще?

UPDATE: чтобы быть более конкретным ...

firstfunction data.txt -f "\d+" 

должен вызывать

secondfunction data.txt --format "\d+" 
+0

@anubhava Для простоты предположим, что мне нужно изменить короткие варианты длинных опций: -f -> --format, -х -> --execute. –

ответ

1

Это удивительно трудная проблема. Bash просто не очень хорошо работает с (слегка) сложными структурами данных, такими как массивы.

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

function firstfunction { 
    local -A map=(['-f']='--format'); 
    local -a args=(); 
    local arg; 
    for arg in "[email protected]"; do 
     if [[ -v map[$arg] ]]; then 
      args+=("${map[$arg]}"); 
     else 
      args+=("$arg"); 
     fi; 
    done; 
    echo ${args[@]+"${args[@]}"}; ## replace echo with secondfunction to run 
}; 
firstfunction; 
## 
firstfunction a b; 
## a b 
firstfunction x -f -fff -f-f -fxy x-f \ -f -f\ -f; 
## x --format -fff -f-f -fxy x-f -f -f --format 

Использование ${args[@]+"${args[@]}"} вместо просто "${args[@]}" для окончательного расширения работ по решению опрометчивого проекта разработчики Баш сделали, чтобы отклонить пустой массив в качестве «несвязанного переменной» если у вас установлен параметр nounset (set -u). См. Bash empty array expansion with `set -u`.


Альтернатива:

function firstfunction { 
    local -A map=(['-f']='--format'); 
    local -a args=("[email protected]"); 
    local -i i; 
    for ((i = 0; i < ${#args[@]}; ++i)); do 
     if [[ -v map[${args[i]}] ]]; then 
      args[i]="${map[${args[i]}]}"; 
     fi; 
    done; 
    echo ${args[@]+"${args[@]}"}; ## replace echo with secondfunction to run 
}; 
+1

Спасибо @bgoldst! Я играл с решением @ anubhava и понял, что мне действительно нужно больше общего. –

+0

Не для nitpicking, но 'firstfunction -fabc' является допустимым аргументом параметра для отправки' abc' с опцией '-f'. Чтобы быть общим, он должен стать '--format abc' или' --format = abc' – anubhava

+0

Здесь вы можете использовать гораздо более простой цикл: 'for arg in" $ @ "; do' – chepner

1

Вы можете использовать getopts для надежного анализа и обработки необязательные аргументы, как это:

firstfunction() { 
    OPTIND=1 
    local arr=() 
    while getopts "f:x:" opt; do 
     case $opt in 
     f) arr+=("--format $OPTARG");; 
     x) arr+=("--execute $OPTARG");; 
     esac 
    done 
    echo "${arr[@]}"; # or call second function here 
} 

firstfunction -fabc -x foobar 
--format abc --execute foobar 

firstfunction -fabc -xfoobar 
--format abc --execute foobar 

firstfunction -f abc -xfoobar 
--format abc --execute foobar 
+0

Да, это правильно @bgoldst. Для надежного способа справиться с этим я бы предложил цикл с использованием 'while getopts' – anubhava

Смежные вопросы