Bash でコマンドライン引数を解析するにはどうすればいいですか? 質問する

Bash でコマンドライン引数を解析するにはどうすればいいですか? 質問する

たとえば、次の行で呼び出されるスクリプトがあるとします。

./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile

またはこれ:

./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile 

それぞれの場合(または 2 つの組み合わせ)で$v、、、$f$dすべて に設定されtrue、 と$outFile等しくなるようにこれを解析する受け入れられた方法は何ですか/fizz/someOtherFile?

ベストアンサー1

Bash スペース区切り(例--option argument:)

cat >/tmp/demo-space-separated.sh <<'EOF'
#!/bin/bash

POSITIONAL_ARGS=()

while [[ $# -gt 0 ]]; do
  case $1 in
    -e|--extension)
      EXTENSION="$2"
      shift # past argument
      shift # past value
      ;;
    -s|--searchpath)
      SEARCHPATH="$2"
      shift # past argument
      shift # past value
      ;;
    --default)
      DEFAULT=YES
      shift # past argument
      ;;
    -*|--*)
      echo "Unknown option $1"
      exit 1
      ;;
    *)
      POSITIONAL_ARGS+=("$1") # save positional arg
      shift # past argument
      ;;
  esac
done

set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters

echo "FILE EXTENSION  = ${EXTENSION}"
echo "SEARCH PATH     = ${SEARCHPATH}"
echo "DEFAULT         = ${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)

if [[ -n $1 ]]; then
    echo "Last line of file specified as non-opt/last argument:"
    tail -1 "$1"
fi
EOF

chmod +x /tmp/demo-space-separated.sh

/tmp/demo-space-separated.sh -e conf -s /etc /etc/hosts
上記のブロックをコピーして貼り付けた出力
FILE EXTENSION  = conf
SEARCH PATH     = /etc
DEFAULT         =
Number files in SEARCH PATH with EXTENSION: 14
Last line of file specified as non-opt/last argument:
#93.184.216.34    example.com
使用法
demo-space-separated.sh -e conf -s /etc /etc/hosts

Bash 等号区切り (例: --option=argument)

cat >/tmp/demo-equals-separated.sh <<'EOF'
#!/bin/bash

for i in "$@"; do
  case $i in
    -e=*|--extension=*)
      EXTENSION="${i#*=}"
      shift # past argument=value
      ;;
    -s=*|--searchpath=*)
      SEARCHPATH="${i#*=}"
      shift # past argument=value
      ;;
    --default)
      DEFAULT=YES
      shift # past argument with no value
      ;;
    -*|--*)
      echo "Unknown option $i"
      exit 1
      ;;
    *)
      ;;
  esac
done

echo "FILE EXTENSION  = ${EXTENSION}"
echo "SEARCH PATH     = ${SEARCHPATH}"
echo "DEFAULT         = ${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)

if [[ -n $1 ]]; then
    echo "Last line of file specified as non-opt/last argument:"
    tail -1 $1
fi
EOF

chmod +x /tmp/demo-equals-separated.sh

/tmp/demo-equals-separated.sh -e=conf -s=/etc /etc/hosts
上記のブロックをコピーして貼り付けた出力
FILE EXTENSION  = conf
SEARCH PATH     = /etc
DEFAULT         =
Number files in SEARCH PATH with EXTENSION: 14
Last line of file specified as non-opt/last argument:
#93.184.216.34    example.com
使用法
demo-equals-separated.sh -e=conf -s=/etc /etc/hosts

${i#*=}「部分文字列の削除」をよりよく理解するには、このガイド`sed 's/[^=]*=//' <<< "$i"`これは、不要なサブプロセスを呼び出す や、不要なサブプロセスを2 つ`echo "$i" | sed 's/[^=]*=//'`呼び出すと機能的に同等です。


getopt[s] で bash を使用する

getopt(1) の制限 (比較的新しい古いgetoptバージョン):

  • 空の文字列の引数を処理できません
  • 空白が埋め込まれた引数を処理できません

最新getoptバージョンではこれらの制限はありません。詳細については、以下を参照してください。ドキュメント


POSIX ゲトプット

さらに、POSIX シェルやその他のシェルでは、getoptsこれらの制限がありません。単純な例を挙げてみましたgetopts

cat >/tmp/demo-getopts.sh <<'EOF'
#!/bin/sh

# A POSIX variable
OPTIND=1         # Reset in case getopts has been used previously in the shell.

# Initialize our own variables:
output_file=""
verbose=0

while getopts "h?vf:" opt; do
  case "$opt" in
    h|\?)
      show_help
      exit 0
      ;;
    v)  verbose=1
      ;;
    f)  output_file=$OPTARG
      ;;
  esac
done

shift $((OPTIND-1))

[ "${1:-}" = "--" ] && shift

echo "verbose=$verbose, output_file='$output_file', Leftovers: $@"
EOF

chmod +x /tmp/demo-getopts.sh

/tmp/demo-getopts.sh -vf /etc/hosts foo bar
上記のブロックをコピーして貼り付けた出力
verbose=1, output_file='/etc/hosts', Leftovers: foo bar
使用法
demo-getopts.sh -vf /etc/hosts foo bar

の利点はgetopts次のとおりです。

  1. より移植性が高く、 などの他のシェルでも動作しますdash
  2. -vf filename典型的な Unix の方法と同様に、複数の単一オプションを自動的に処理できます。

の欠点は、追加コードなしでは短いオプション ( 、ではなく)getoptsしか処理できないことです。-h--help

そこにはgetopts チュートリアルこれは、すべての構文と変数の意味を説明しています。bash には、 もありhelp getopts、参考になるかもしれません。

おすすめ記事