Bash - 평가 없이 동적 메뉴 선택을 만드는 방법

Bash - 평가 없이 동적 메뉴 선택을 만드는 방법

저는 Docker 환경을 위한 스크립트를 작성하고 있는데 제가 빠진 구멍에 갇혀 있는 것 같습니다.

#!/bin/bash

set -euo pipefail

# Variables
gituser="modem7"
gitrepo="docker-devenv"
gitfolder="Environments"
buildername="DockerDevBuilder"

# Colours
RED="\e[31m"
GREEN="\e[32m"
END="\e[0m"

echo "========================================="
printf "        Checking Dependencies\n"
echo "========================================="
printf "Checking if dependencies are installed...\n"
pkg_list=(docker jq)
tc() { set ${*,,} ; echo ${*^} ; }
for pkg in "${pkg_list[@]}"
do
  titlecase=$(tc $pkg)
  isinstalled=$(dpkg-query -l $pkg > /dev/null 2>&1)
    if [ $? -eq 0 ];
     then
       printf "~ $titlecase is...${GREEN}installed${END}\n"
     else
       printf "~ $titlecase is...${RED}not installed${END}\n"
       printf "Exiting Script. Install $pkg.\n"
       echo "========================================="
       exit
    fi
done
echo "========================================="

cat << "EOF" 
      ____             _             
     |  _ \  ___   ___| | _____ _ __ 
     | | | |/ _ \ / __| |/ / _ | '__|
     | |_| | (_) | (__|   |  __| |   
     |____/ \___/ \___|_|\_\___|_|   
=========================================
EOF

PS3="Choose Option: "
dev_list=($(curl -fks https://api.github.com/repos/$gituser/$gitrepo/contents/$gitfolder | jq '. [] | .name' | tr -d '[]," '))
dev_list_array="${dev_list[*]}"
dev_list_array_pipe="${dev_list_array// /|}"
dev_list+=( "Prune" "Quit" )
echo -e "\nSelect an option:\n"
select dev_name in "${dev_list[@]}"; do
echo -e "\nYou've selected ${GREEN}${dev_name}${END}\n"
lowerdev=$(echo $dev_name | tr '[:upper:]' '[:lower:]')
    eval "case \"$dev_name\" in
      "$dev_list_array_pipe")
          echo "Creating buildx builder..."
          if docker buildx create --use --name "$buildername" > /dev/null 2>&1; then
              echo ""
              echo "Builder $buildername created"
            else
              echo "Builder already created, using $buildername"
              docker buildx use "DockerDevBuilder"
              echo ""
          fi
          echo "Creating $dev_name Environment..."
          docker buildx build --rm=true --build-arg BUILDKIT_INLINE_CACHE=1 --load -t $lowerdev:dev https://github.com/$gituser/$gitrepo.git#:$gitfolder/$dev_name \
          && clear \
          && echo "=========================================" \
          && echo "Activating $dev_name Dev Environment..." \
          && echo "Press CTRL + D or type exit to leave the container" \
          && docker run --rm -it --name "$dev_name"Dev"$RANDOM" --hostname "$dev_name"Dev"$RANDOM" "$lowerdev:dev"
          break
          ;;
      "Prune")
          echo "Clearing Docker cache..."
          docker system prune -af
          echo ""
          echo "Removing Docker buildx builder..."
          if docker buildx rm "$buildername" > /dev/null 2>&1; then
              echo ""
              echo "Builder $buildername removed"
            else
              echo "Builder already removed, no action performed"
              echo ""
          fi          
          exec bash $0
          ;;
      "Quit")
          echo "Exiting script"
          exit
          ;;
       *)
          echo "invalid option $REPLY"
          ;;
    esac"
done

exit 0

나는 현재 " eval "case \"$dev_name\" in"를 사용하고 있지만 내가 읽은 바에 따르면 이것은 문제가 있는 것 같습니다.

작동하지만 그러한 결과를 얻는 더 좋은 방법이 있는지 확실하지 않습니다.

이러한 옵션은 폴더 이름을 기반으로 생성됩니다.환매 계약, 그러나 eval 사용을 제거하는 방법을 잘 모르겠습니다. 내가 쓸데없는 걱정을 하고 있는 걸까?

답변1

이 문제는 다음 변경 사항으로 해결되었습니다.

#!/bin/bash

set -euo pipefail
shopt -s extglob

# Variables
gituser="modem7"
gitrepo="docker-devenv"
gitfolder="Environments"
buildername="DockerDevBuilder"
failuremsg=""

# Colours
RED="\e[31m"
GREEN="\e[32m"
END="\e[0m"

echo "========================================="
printf "        Checking Dependencies\n"
echo "========================================="
printf "Checking if dependencies are installed...\n"
pkg_list=(docker jq)
tc() { set ${*,,} ; echo ${*^} ; }
for pkg in "${pkg_list[@]}"
do
  titlecase=$(tc $pkg)
  isinstalled=$(dpkg-query -l $pkg > /dev/null 2>&1)
    if [ $? -eq 0 ];
     then
       printf "~ $titlecase is...${GREEN}installed${END}\n"
     else
       printf "~ $titlecase is...${RED}not installed${END}\n"
       printf "Exiting Script. Install $pkg.\n"
       echo "========================================="
       exit
    fi
done
echo "========================================="

cat << "EOF" 
      ____             _             
     |  _ \  ___   ___| | _____ _ __ 
     | | | |/ _ \ / __| |/ / _ | `__|
     | |_| | (_) | (__|   |  __| |   
     |____/ \___/ \___|_|\_\___|_|   
=========================================
EOF

ctrl_c () {
    echo -e "\nUser pressed Ctrl + C. Exiting script...\n"
    exit 1
}

# Trap CTRL+C
trap ctrl_c INT

PS3="Choose Option: "
dev_list=($(curl -fks https://api.github.com/repos/$gituser/$gitrepo/contents/$gitfolder | jq '. [] | .name' | tr -d '[]," '))
dev_env_options=${dev_list[0]};
for ((i=1; i<${#dev_list[@]}; i++)); do
        dev_env_options="$dev_env_options|${dev_list[i]}"
done
echo -e "\nSelect an option:\n"
select dev_name in "${dev_list[@]}" "Prune" "Quit"; do
echo -e "\nYou've selected ${GREEN}${dev_name}${END}\n"
lowerdev=$(echo $dev_name | tr '[:upper:]' '[:lower:]')
    case $dev_name in
      +($dev_env_options))
          echo "Creating buildx builder..."
          if docker buildx create --use --name "$buildername" > /dev/null 2>&1; then
              echo -e "\nBuilder $buildername created..."
            else
              echo -e "Builder already created, using "$buildername"...\n"
              docker buildx use "$buildername"
          fi
          echo "Creating $dev_name Environment..."
          docker buildx build --rm=true --build-arg BUILDKIT_INLINE_CACHE=1 --load -t $lowerdev:dev https://github.com/$gituser/$gitrepo.git#:$gitfolder/$dev_name
          clear
          echo "========================================="
          echo "Activating $dev_name Dev Environment..."
          echo "Press CTRL + D or type exit to leave the container"
          docker run --rm -it --name "$dev_name"Dev"$RANDOM" --hostname "$dev_name"Dev"$RANDOM" "$lowerdev:dev" & dockerrun_pid=$!
          break
          ;;
      "Prune")
          echo "Clearing Docker cache..."
          docker system prune -af
          echo -e "\nRemoving Docker buildx builder..."
          if docker buildx rm "$buildername" > /dev/null 2>&1; then
              echo -e "\nBuilder $buildername removed"
            else
              echo -e "Builder already removed, no action performed\n"
          fi
          exec bash $0
          ;;
      "Quit")
          echo "Exiting script..."
          break
          ;;
       *)
          echo "Invalid option $REPLY"
          exec bash $0
          ;;
    esac
done

exit 0

관련 정보