getopts以降のスクリプトパラメータの解析

getopts以降のスクリプトパラメータの解析

以下を使用してスイッチを実装するスクリプトがあります。選択項目のインポート。ただし、次のパラメーターを参照できません。

私のスクリプトは、ローカル開発環境でWebサイトのバックアップをバックポートするために使用されます。-pいくつかの展開後の手順を実行するためのスイッチを追加しました。これは私の構文です。

backport -p /path/to/website_backup.sql.gz

そのため、切り替える前にファイルが指定されたか、ファイルが正しいかテストしています。ファイル名のパスが唯一のパラメータであるため、必ず必要であると仮定でき、最初のパラメータ($1)になります。

if [[ $# -eq 0 ]] ; then
  echo 'Specifcy the sql file to backport.';
  exit 0;
fi

if [[ ! -f "$1" ]]; then
  echo "$1 is not a valid file.";
  exit 0;
fi

私が見つけたこの回答getoptsを使用してスイッチパラメータを解析する方法の例を示します。

while getopts "p" opt; do
  case $opt in
    p) p_post_deploy=true ;; # Handle -a
  esac
done

もちろん、$1getoptsを実装した後はasパラメータを使用しても機能しません。スイッチがなくても大丈夫です。ただし、最初のパラメータであるスイッチを追加すると、スクリプトがファイルかどうかをテストします。

$ backport -p /path/to/website_backup.sql.gz
-p is not a valid file.

そのため、スイッチの導入により、コマンドの特定の位置に表示されるパラメータに依存できなくなりました。$2スイッチがないと、ファイル名引数が2番目の引数になることができないため、ハードコーディングは機能しません。私はスイッチの後にパラメータを受け入れ、新しいスイッチ自体を処理するためにコードだけを更新しながら、後で新しいスイッチを導入できるようにするソリューションを望んでいます。後で移動することができます)新しいスイッチの導入)。

getoptsを使用してスイッチを解析する方法を教えてくれるunix.stackexchangeの質問に対する答えを見てみました。答えの一つ$*残りのパラメータを表す変数と呼ばれます。

if [[ "$*" -eq 0 ]] ; then
  echo 'Specifcy the sql file to backport.';
  exit 0;
fi

しかし、使用しようとすると、構文を正確に表現できず、解析エラーが発生します。

~/scripts/backport: line 14: [[: /d/Downloads/database.sql.gz: syntax error: operand expected (error token is "/d/Downloads/database.sql.gz")

getopsの後にファイル名パラメータをテストする方法は?


現在のスクリプトバージョンは次のとおりです。

$ cat backport
#!/bin/bash

set -e

while getopts "p" opt; do
  case $opt in
    p) p_post_deploy=true ;;
  esac
done

shift $(($OPTIND - 1))
# testing what this variable looks like
printf "Remaining arguments are: %s\n" "$*"

if [[ "$*" -eq 0 ]] ; then
  echo 'Specifcy the sql file to backport.';
  exit 0;
fi

if [[ ! -f "$*" ]]; then
  echo "$* is not a valid file.";
  exit 0;
fi

drush @local.dev sql-drop -y ;
zcat $1 | drush @local.dev sqlc ;
drush @local.dev cr;

if [ ! -z "$p_post_deploy" ] ; then
  echo "Running post-deploy..."
  SCRIPT_PATH=$(dirname "$BASH_SOURCE")
  source "$SCRIPT_PATH/post-deploy"
  post_deploy
fi

答え1

コミュニケーションがスムーズにできなかったので、私のせいにするしかありませんが、クサラナンダが私が探していた答えをコメントしてくれました。

getopts構文解析スイッチを使用した後

while getopts "p" opt; do
  case $opt in
    p) p_post_deploy=true ;;
  esac
done

この行

shift "$((OPTIND - 1))"

すべてのスイッチはパラメータリストから削除されるため、スイッチがないかのように位置パラメータを再利用できます。

シェルはOPTIND自動的にリセットされません。手動でリセットする必要があります。

答え2

テスト構造の適用

if [[ "$*" -eq 0 ]]

不正確です。-eqに使用されます整数そして、$*引数リストがその数ではなく残りのすべての引数を参照することを考えると、残りの引数リストに1つの要素しか含まれていない限り、テスト構成は構文エラーを生成するしかありません。整数を表します(これは達成するものではありません)。

実際の作業では、「非オプションパラメータ」(例:いいえ-<some letter>ランダムな順序を許可する限り(つまり、ファイル名が最後に来なければならないことを指定しない限り)、オプション引数とともに「通知」が前に続きます。を使用するには、getoptsファイル名をオプション引数として指定したい場合があります-f <filename>。その後利用できます

while getopts "pf:" opt; do
  case $opt in
    p)
       p_post_deploy=true
    ;;
    f)
       backportfile=$OPTARG
    ;;
  esac
done

getoptsファイル名を指定しないと、自動的にエラーが発生します。

./test.sh: option requires an argument -- f

その後、後でファイルが存在するかどうかをテストできます。

if [[ ! -f "$backportfile" ]]
then
  echo "$backportfile is not a valid file"
  exit 1
fi

関連情報