1. ホーム
  2. bash

[解決済み] Bashでコマンドライン引数を解析するには?

2022-03-14 09:21:19

質問

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

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

とか、これとか。

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

これを解析して、それぞれの場合(またはその組み合わせ)には、どのような方法があるのでしょうか。 $v , $f および $d はすべて true$outFile と同じになります。 /fizz/someOtherFile ?

解決方法は?

バッシュ スペースセパレート(例. --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 Equals-Separated(例. --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#*=} でquot;Substring Removal"を検索してください。 このガイド . と機能的に同等です。 `sed 's/[^=]*=//' <<< "$i"` を呼び出すか、不要なサブプロセスを呼び出す `echo "$i" | sed 's/[^=]*=//'` を呼び出すものです。 のような不要なサブプロセスです。


getopt[s]でbashを使う。

getopt(1) の制限事項 (古いもの、比較的新しいもの) getopt のバージョン)。

  • 空文字列の引数は扱えません
  • 空白文字が埋め込まれた引数を扱えない

より新しい getopt のバージョンでは、これらの制限はありません。詳しくは、これらの ドキュメント .


POSIX getopts

さらに、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 というのがありますが、これは参考になるかもしれません。