1

私はいくつかの仕事を自動化するためにbashスクリプトを書いていますが、それまでの間bashで練習しています。私はいくつかの git のクローン作成と更新を自動化するスクリプトを書いています。私のスクリプトには 3 つのオプション (-g、-f、-h) があります。誰かが -h と入力すると、ヘルプ メッセージが表示されます (これは私が書きましたが、以下では省略しています)。誰かが -g と入力すると、少なくとも 1 つの引数を受け入れる必要がありますが、2 つ目の引数をオプションとして受け入れることもできます。最初のものは複製するリポジトリの URL になり、2 つ目は複製先のディレクトリになります。一方、誰かが -f と入力した場合、スクリプトは 1 つの引数、つまりファイル名だけを取得する必要があります。次に、ファイルを1行ずつ読み取り、ファイル内のgit urlごとにgitのクローン作成と更新を行います。

スクリプトを実行すると、各オプションに対して次のエラー メッセージが表示されます。オプションを指定せずに呼び出した場合、または有効なオプションの後に他の引数を指定して呼び出した場合でも、何もせず、次の値が返されます。

./gitupdate.sh: option requires an argument -- g

私のコードでは何とか $2 と $3 を使用していないと思います。しかし、-h を渡すと、ヘルプ関数を呼び出してメッセージを表示するだけで済み、他の引数を使用する必要はありません。

問題は、 getopts を使用してユーザーが指定したオプション名を取得する下部に何か問題があるためだと思います。私のコードでは、オプションは最初の引数 $1 であり、2 番目の $2 は指定されたオプションに応じて URL またはファイル名であり、$3 は -g オプションでのみ機能するオプションの引数であると想定しています。

以下に私のコードを見つけることができます:

#!/bin/bash

declare default_directory=$HOME
declare action
declare src

function clone_repo() {
    if [ -n "$2" ]; then
        if [ "$(ls -A "$2" 2>/dev/null)" ]; then
            cd "$2"
        else
            git clone "$1" "$2"
        fi
    else
        git clone "$1"
        #TODO: Get the directory name created by cloning
                #      and cd to it.
    fi

    git remote add upstream "$1"
    git fetch upstream
}

function read_repos_from_file() {
    if [ -f "$1" ]; then
        while read -r line; do
            clone_repo "$line" "$2"
        done < "$1"
    else
        echo -e "Error: The specified file could not be found."
        exit 1
    fi
}

while getopts "f:h:r" option
do
    case "${option}" in
        f) action=read_repos_from_file; src="$OPTARG";;
        g) action=clone_repo; src="$OPTARG";;
        h) help ; exit 1 ;;
    esac
done

shift $((OPTIND-1))

[ -z "$action" ] && ( help; exit 1 )

誰かが私を助けることができれば、私はうれしいです.

編集:上記のコードのいくつかのタイプミスを修正しました。エラーメッセージを更新しました。スクリプトが正しく動作しません。コードを何か変更して何かを実行させ、実際に $2 と $3 の引数を取得する必要があると思います。-h オプションが渡された場合、ヘルプメッセージも表示されず、以前に作成したヘルプ関数を呼び出すだけです。どうにかして getopts の部分を変更する必要があるかもしれません。

EDIT 2:アドバイスされた変更を行い、上記のコードを変更しました。

4

1 に答える 1

1

git()関数定義の始まりです (function関数名の後に括弧が続く場合、キーワードはオプションです)。関数を呼び出したい場合はgit()、最初に関数を定義し、括弧なしで呼び出す必要があります。

function git() {
  # do stuff
}

git

ただし、既存のバイナリと同じ名前の関数を作成することはお勧めできません。あなたの場合、おそらくgit cloneファイルから読み取った行で呼び出す必要があります。

while read -r line; do
  git clone "$line"
done < "${file}"

編集:質問が大幅に変更されたため、更新されました。

あなたの引数の処理は… 率直に言って、奇妙です。オプション パーサーを使用している場合、そのオプション パーサーの動作を回避するべきではありません。引数が 1 つだけ"g:"のオプションを意味します。-g複数の引数を持つオプションにしようとしないでください。そのうちの1つはオプションです。出力ディレクトリに追加の (オプションの) 引数が必要な場合は、それを別のオプション (例: "d:") またはオプション以外の引数にします。

オプション処理を次のように変更することをお勧めします。

while getopts "f:g:h" option; do
  case "$option" in
    f) action=file; src="$OPTARG";;
    g) action=repo; src="$OPTARG";;
    h) help; exit 1;;
  esac
done

shift $((OPTIND-1))

[ -z "$action" ] && ( help; exit 1 )

この「$@」の後、オプション以外の引数 (この場合はオプションの出力ディレクトリ) のみが保持されるため、次のように関数を呼び出すことができます。

$action $src "$@"

関数は次のように簡略化されています。

function repo() {
  if [ -n "$2" ]; then
    if [ "$(ls -A "$2" 2>/dev/null)" ]; then
      cd "$2"
    else
      git clone "$1" "$2"
    fi
  else
    git clone "$1"
  fi
  ...
}

function file() {
  if [ -f "$1" ]; then
    while read -r line; do
      repo "$line" "$2"
    done < "$1"
  else
    echo "Error: The specified file could not be found."
    exit 1
  fi
}

より一般的な注意として、名前をより自明なものにする必要があります。clone_repoリポジトリのクローンを作成したり、ファイルからリポジトリを読み取ったりするための関数のより適切な名前は、それぞれと のようなものread_repos_from_fileです。また、リポジトリのクローン作成をトリガーするオプションのニーモニックとして-corの方が適しています。-r

于 2013-07-11T12:30:57.850 に答える