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

#bash

Вопрос:

Я хочу запустить определенный исполняемый файл в зависимости от переменной моего скрипта cur_num

У меня есть этот код, где пути «случайны», что означает, что они не имеют никакого отношения к безопасности cur_num :

 run() {
    if [ $cur_num = "0" ]
        then ~/pathDirName0/execFile0 
    elif [ $cur_num = "1" ] 
        then ~/pathDirName1/execFile1
    elif [ $cur_num = "2" ] 
        then ~/pathDirName2/execFile2 
    elif [ $cur_num = "3" ] 
        then ~/pathDirName3/execFile3
    elif [ $cur_num = "4" ] 
        then ~/pathDirName4/execFile4
    fi
}
 

В случае, если есть еще много случаев, это приводит к очень длинному if - elif заявлению.
Поскольку в bash нет перечислений для построения cur_num отношения — путь, есть ли более чистый способ получить желаемый путь динамически, а не с большим количеством if s?

Комментарии:

1. ~/pathDirName"$cur_num"/execFile"$cur_num" ? no enums in bash to build the cur_num- path relation Зачем вам для этого использовать перечисления? Вы можете использовать ассоциативные массивы bash или массивы bash.

2. пути являются «случайными», то есть они не имеют никакого отношения к безопасности cur_num , поэтому мне нужно будет связать cur_num их с путем, который будет жестко закодированной строкой

3. Тогда это просто массив.

4. Как в: paths=(/path/to/execA /path/to/execB); exec=${paths[cur_num]} для минимального примера с 2 путями.

5. Если $cur_num только вы не можете принимать нецелые значения; тогда вам нужен ассоциативный массив (Bash 4.0 ).

Ответ №1:

Примерное дело

 case $cur_num in
      0) ~/pathDirName0/execFile0;;
      1) ~/pathDirName1/execFile1;;
      2) ~/pathDirName2/execFile2;;
      ...
esac
 

Комментарии:

1. это работает, спасибо

Ответ №2:

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

set -- ~/pathDirName0/execFile0 ~/pathDirName1/execFile1 ~/pathDirName2/execFile2 ~/pathDirName3/execFile3 ~/pathDirName4/execFile4

Затем, чтобы получить доступ к этим элементам с помощью индекса, вы делаете $x , где x находится индекс элемента.

Теперь ваш код будет выглядеть примерно так:

 run() {
    original="$@"

    : $((cur_num =1)) # Positional param indexing starts from 1

    set -- ~/pathDirName0/execFile0 ~/pathDirName1/execFile1 
           ~/pathDirName2/execFile2 ~/pathDirName3/execFile3 
           ~/pathDirName4/execFile4

    eval "$"$cur_num"" # cur_num = 1, accesses $1 == execFile0

    set -- $original # Restore original args
}
 

Метод, который и менее, и более избитый, который работал бы для индексов выше 9 и не связывался бы с исходными позиционными параметрами и не использовал бы eval

 run() {
    count=0

    for item in "$@"; do
        [ "$count" = "$cur_num" ] amp;amp; {
            "$item"
            return        
        }

        : "$((count =1))"
    done

    echo "No item found at index '$cur_num'"
}

cur_num="$1" # Assuming first arg of script.

run ~/pathDirName0/execFile0 ~/pathDirName1/execFile1 
    ~/pathDirName2/execFile2 ~/pathDirName3/execFile3 
    ~/pathDirName4/execFile4
 

Комментарии:

1. Это выравнивает исходные позиционные параметры в строку, которая затем подвергается разделению на слова.

2. Я предполагаю, что тогда код можно было бы изменить, чтобы удалить set и вызвать run со многими параметрами, чтобы он не путался с исходными ? Он получит свой собственный массив из параметров

3. Пожалуйста, проверьте правку.