스크립트의 옵션에 대한 인수를 구문 분석하는 중 오류가 발생했습니다. 쉘 스크립트의 예기치 않은 옵션

스크립트의 옵션에 대한 인수를 구문 분석하는 중 오류가 발생했습니다. 쉘 스크립트의 예기치 않은 옵션

스크립트에 옵션을 전달하기 위해 매개변수를 구문 분석하려고 합니다.

하지만 다음 오류가 표시됩니다. Unexpected option: -u 아래 루프를 제외하고:

$ gitpratico -u "<usuario_github>" -p "<repositorio_remoto_github>" -c "comentario criação/alteração repositorio"

Unexpected option: -u

O gitpratico deve ser executado dentro da pasta do projeto somente uma unica vez

Enter: gitpratico [ -u "user_git" | --user ] [ -p "project_name" | --proj ] 
    [ -c "comemt alter project" | --commit ] [ -h | --help]
    

Unexpected option: -u

O gitpratico deve ser executado dentro da pasta do projeto somente uma unica vez

Enter: gitpratico [ -u "user_git" | --user ] [ -p "project_name" | --proj ] 
    [ -c "comemt alter project" | --commit ] [ -h | --help]
    

Unexpected option: -u

O gitpratico deve ser executado dentro da pasta do projeto somente uma unica vez

Enter: gitpratico [ -u "user_git" | --user ] [ -p "project_name" | --proj ] 
    [ -c "comemt alter project" | --commit ] [ -h | --help]

이 문제를 어떻게 해결할 수 있나요?

나는 성공하지 못한 채 getopt를 사용해 보았습니다.

SHORT=c:p:u:h
LONG=commit:proj:user:help
OPTS=$(getopt -a -n ${0##*/} --options $SHORT --longoptions $LONG -- "$@")
#!/bin/bash

GIT="$(which git)"

CURL="$(which curl)"

#USER_GIT="${1}"

#PROJECT_NAME="${2}"

<<COMENTARIO
O script "gitpratico_multiuser" foi criado para mais de um usuario que tem acesso 
a mesma estação de trablho em horarios diferentes possa usar o script sem 
precisar ficar digitando a chave token toda vez que usar o script,
basta colocar a "chave token" de todos os usuarios github e os usuario github 
no vetor deste script assim se tivermos tres usuarios 
que acessam a maquina em horarios diferentes todos eles tem que 
estar configurados no vetor com suas respectivas chaves tokens 
na mesma posição em que se encontra o seu usuario no vetor 
e o ssh configurado no github entao basta 
apenas digitar "gitpratico <username_git> <nome_projeto>" para criar os repositorios.
COMENTARIO

USERS_GIT=("usuario1" "usuario2" "github_usuario3")

## Pegando os hosts dos usuarios githubs em ~/.ssh/config e colocando no Vetor
HOSTS_GITHUB_USERS=($(grep "host-" ~/.ssh/config | sed 's/Host\s//g;'))

#Coloque sua chave token no vetor para verificar
ACESS_TOKEN=("chave1" chave2" "chave_token_github_usuario3")

function help(){
    echo
    echo "O ${0##*/} deve ser executado dentro da pasta do projeto somente uma unica vez"
    echo
    echo -e "Usage: ${0##*/} [ -u \"user_git\" | --user ] [ -p \"project_name\" | --proj ] 
    [ -c \"comemt alter project\" | --commit ] [ -h | --help]
    "
    echo
}

#SHORT=c:p:u:h
#LONG=commit:proj:user:help
#OPTS=$(getopt -a -n ${0##*/} --options $SHORT --longoptions $LONG -- "$@")

if [ $# -lt 3 ]; then
  help
   else

##Os c:p:u:user:proj:commit: [obriga a digitar um argumento após a opção]
while getopts c:p:u:user:proj:commit:h,help option
do
  case "${option}" in
    "-u" |" --user")
     USER_GIT="${OPTARG}"
    ;;
    "-p" | "--proj")
     PROJECT_NAME="${OPTARG}"
    ;;
    
   "-c"|"--commit")
    COMENTARIO="${OPTARG}"
   ;;

   "-h"|"--help")
    help
   ;;

   --)
    help
   ;;

   *)
     echo "Unexpected option: ${1}"
     help
    ;;
  esac
done
    
for ((i = 0; i < "${#USERS_GIT[@]}"; i++))
    do
       
        if [[ "${USERS_GIT[$i]}" == "${USER_GIT}" ]]; then
            
            #Criando os repositprios remotamente sem logar no github
            ${CURL} -i -H "Authorization: token ${ACESS_TOKEN[$i]}" -d "{\"name\":\"${PROJECT_NAME}\",\"private\":false}" https://api.github.com/user/repos
            
            if [[ "${PROJECT_NAME}" != "${PWD[@]/*\/}" ]]; then
                
                mkdir ${PROJECT_NAME}
                
                cd ${PROJECT_NAME}
                
                #Inicializa o repositório
                ${GIT[@]/*\/} init
                
                ##Cria um README no projeto
                echo "## README ${PROJECT_NAME}" >> README.md
                echo "### PROJETO criado com o script gitpratico" >> README.md
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT[@]/*\/} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT[@]/*\/} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT[@]/*\/} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:$USERS_GIT/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config

                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT[@]/*\/} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main
            
            elif [[ ${PROJECT_NAME} == ${PWD[@]/*\/} ]]; then
                
                README="$(ls -1 README.md 2> /dev/null)"
                
                #Inicializa o repositório
                ${GIT[@]/*\/} init
                
                if [ -z "${README}" ]; then
                    ##Cria um README caso o projeto nao tenha nada na pasta ainda
                    echo "## README ${PROJECT_NAME}" >> README.md
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                else
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                fi
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT[@]/*\/} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT[@]/*\/} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT[@]/*\/} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:${USER_GIT}/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config
                
                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT[@]/*\/} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main

            fi #Fim PWD

        fi #Fim USERS_GIT
        
done #Fim for

내 스크립트가 다음과 같이 변경되었습니다.

#!/bin/bash

GIT="$(which git)"

CURL="$(which curl)"

#USER_GIT="${1}"

#PROJECT_NAME="${2}"

<<COMENTARIO
O script "gitpratico_multiuser" foi criado para mais de um usuario que tem acesso 
a mesma estação de trablho em horarios diferentes possa usar o script sem 
precisar ficar digitando a chave token toda vez que usar o script,
basta colocar a "chave token" de todos os usuarios github e os usuario github 
no vetor deste script assim se tivermos tres usuarios 
que acessam a maquina em horarios diferentes todos eles tem que 
estar configurados no vetor com suas respectivas chaves tokens 
na mesma posição em que se encontra o seu usuario no vetor 
e o ssh configurado no github entao basta 
apenas digitar "gitpratico <username_git> <nome_projeto>" para criar os repositorios.
COMENTARIO

USERS_GIT=("usuario1" "usuario2" "github_usuario3")

## Pegando os hosts dos usuarios githubs em ~/.ssh/config e colocando no Vetor
HOSTS_GITHUB_USERS=($(grep "host-" ~/.ssh/config | sed 's/Host\s//g;'))

#Coloque sua chave token no vetor para verificar
ACESS_TOKEN=("chave1" "chave2" "chave_token_github_usuario3")

function help(){
    
    echo -e "\nO ${0##*/} deve ser executado dentro da pasta do projeto somente uma unica vez\n"
    echo -e "Usage: ${0##*/} [ -u \"user_git\" | --user ]\n\n[ -p \"project_name\" | --proj ]\n\n[ -c \"comemt alter project\" | --commit ]\n\n[ -h | --help]\n\n"
}

if [ $# -lt 3 ]; then
  help
   else

##Os : [obriga a digitar um argumento após a opção u,p,user,proj]
while getopt u:p:c:user:proj:coment:h,help option
do
  case "${option}" in
    -u|--user)
     USER_GIT="${OPTARG}"
    ;;
    -p|--proj)
     PROJECT_NAME="${OPTARG}"
    ;;

    -c|--coment)
    COMENTARIO="${OPTARG}"
    ;;
    
   -h|--help)
    help
   ;;

   --)
    help
   ;;

   *)
     echo "Unexpected option: ${1}"
     help
    ;;
  esac
done
    
for ((i = 0; i < "${#USERS_GIT[@]}"; i++))
    do
       
        if [[ "${USERS_GIT[$i]}" == "${USER_GIT}" ]]; then
            
            #Criando os repositprios remotamente sem logar no github
            ${CURL} -i -H "Authorization: token ${ACESS_TOKEN[$i]}" -d "{\"name\":\"${PROJECT_NAME}\",\"private\":false}" https://api.github.com/user/repos
            
            if [[ "${PROJECT_NAME}" != "${PWD[@]/*\/}" ]]; then
                
                mkdir ${PROJECT_NAME}
                
                cd ${PROJECT_NAME}
                
                #Inicializa o repositório
                ${GIT} init
                
                ##Cria um README no projeto
                echo "## README ${PROJECT_NAME}" >> README.md
                echo "### PROJETO criado com o script gitpratico" >> README.md
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:$USERS_GIT/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config

                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main
            
            elif [[ ${PROJECT_NAME} == ${PWD[@]/*\/} ]]; then
                
                README="$(ls -1 README.md 2> /dev/null)"
                
                #Inicializa o repositório
                ${GIT} init
                
                if [ -z "${README}" ]; then
                    ##Cria um README caso o projeto nao tenha nada na pasta ainda
                    echo "## README ${PROJECT_NAME}" >> README.md
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                else
                    echo "### PROJETO criado com o script gitpratico" >> README.md
                fi
                
                ## Adiciona todos os arquivos existentes na pasta
                ${GIT} add .
                
                #echo "Digite um comentário sobre o que você fez no projeto: "
                #echo
                #read -p "Entre com o comentario: " COMENTARIO
                
                ##Comitando o projeto
                ${GIT} commit -m "${COMENTARIO}"
                
                #Modifica o branch atual criado pelo commit
                ${GIT} branch -M main
                
                #Apos fazer qualquer alteração estas configurações permiten fazer apenas "git push" no projeto
                #Sem precisar digitar toda vez: git push [email protected]:${USER_GIT}/${PROJECT_NAME}.git main
                #Todos os repositórios criados com o script terão "branch master"
                
echo "[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote \"origin\"]
        url = git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch \"main\"]
        remote = origin
        merge = refs/heads/main"> .git/config
                
                echo "Copie e cole seu token caso nescessário ou digite a senha configurada na chave ssh do github"
                echo
                ${GIT} push git@${HOSTS_GITHUB_USERS[${i}]}:${USERS_GIT[${i}]}/${PROJECT_NAME}.git main

            fi #Fim PWD

        fi #Fim USERS_GIT
        
done #Fim for

fi

스크립트에서 이 오류를 제거했는데도 여전히 무한 반복되고 예상치 못한 옵션이 표시됩니다. getopts를 getopt로 변경했습니다.

예상치 못한 옵션: -u 등

답변1

(간결하게 하기 위해 이 답변은 질문에서 묻는 코드의 옵션 구문 분석 오류에 중점을 두고 있지만 코드에 있을 수 있는 다른 문제는 무시합니다.)

긴 옵션을 지원하지 않는 것 외에도 표준 getopts유틸리티는 옵션 문자를 배치합니다.아니요주어진 변수의 대시.

이는 case명령줄 구문 분석 루프의 명령문이 대시 없이 test u, p및 로 변경되어야 함을 의미합니다. 이 경우 오류 메시지는 알 수 없는 옵션과 관련이 없을 수 있으므로 대신 언급하도록 변경될 수도 있습니다 . 또한 더 이상의 처리가 불가능하므로 오류 메시지의 출력을 따라야 한다고 믿어집니다 .ch*-$option$1exit 1

답변2

getopts(s 포함)은 표준 유틸리티이며 긴 옵션을 지원하지 않으므로 수단 getopts c:p:u:user:proj:commit:h등은 carg를 취하는 옵션이고, while 등은 긴 옵션을 지원하지 않는 (단일 문자) 옵션입니다. 거기에 문자를 두 번 지정하면 어떻게 될지 모르겠습니다.puuser

(s 없이) 사용하려면 getoptutil-linux나 Busybox의 향상된 버전이 필요하며 올바르게 사용하려면 주의가 필요합니다. 예를 들어 참조하십시오.내 이전 답변은 여기에 있습니다.(참조가 가장 찾기 쉽기 때문에 선택했습니다.) 전통적인 getopt구현은 공백 등에서는 잘 수행되지 않으며 긴 옵션도 지원하지 않습니다.

게다가 getopts쉘에서 구현하더라도 위치 매개변수 자체는 변경되지 않습니다. 따라서 해당 오류를 인쇄하면 echo "Unexpected option: ${1}"실제 첫 번째 인수가 항상 스크립트에 인쇄되며 이는 문제의 오류와 관련이 없을 수 있습니다. 예를 들어 여기서는 항상 다음 -a으로 시작합니다 $1.

$ sh -c 'while getopts ab opt; do echo "$opt $1"; done' sh -a -b -c
a -a
b -a
Illegal option -c
? -a

관련 정보