Comment puis-je parse des arguments de ligne de commande dans Bash

Mots clés : bashcommand-linescriptingargumentsgetoptsbash

meilleur 5 Réponses Comment puis-je parse des arguments de ligne de commande dans Bash

vote vote

94

cat >/tmp/demo-space-separated.sh <<'EOF' #!/bin/bash  POSITIONAL=() while [[ $# -gt 0 ]]; do   key="$1"    case $key in     -e|--extension)       EXTENSION="$2"       shift # past argument       shift # past value       ;;     -s|--searchpath)       SEARCHPATH="$2"       shift # past argument       shift # past value       ;;     -l|--lib)       LIBPATH="$2"       shift # past argument       shift # past value       ;;     --default)       DEFAULT=YES       shift # past argument       ;;     *)    # unknown option       POSITIONAL+=("$1") # save it in an array for later       shift # past argument       ;;   esac done  set -- "${POSITIONAL[@]}" # restore positional parameters  echo "FILE EXTENSION  = ${EXTENSION}" echo "SEARCH PATH     = ${SEARCHPATH}" echo "LIBRARY PATH    = ${LIBPATH}" 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 -l /usr/lib /etc/hosts 
FILE EXTENSION  = conf SEARCH PATH     = /etc LIBRARY PATH    = /usr/lib 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 -l /usr/lib /etc/hosts 
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       ;;     -l=*|--lib=*)       LIBPATH="${i#*=}"       shift # past argument=value       ;;     --default)       DEFAULT=YES       shift # past argument with no value       ;;     *)       # unknown option       ;;   esac done echo "FILE EXTENSION  = ${EXTENSION}" echo "SEARCH PATH     = ${SEARCHPATH}" echo "LIBRARY PATH    = ${LIBPATH}" 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 -l=/usr/lib /etc/hosts 
FILE EXTENSION  = conf SEARCH PATH     = /etc LIBRARY PATH    = /usr/lib 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 -l=/usr/lib /etc/hosts 
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 
vote vote

83

myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile myscript -v -f -d -o/fizz/someOtherFile -- ./foo/bar/someFile myscript --verbose --force --debug ./foo/bar/someFile -o/fizz/someOtherFile myscript --output=/fizz/someOtherFile ./foo/bar/someFile -vfd myscript ./foo/bar/someFile -df -v --output /fizz/someOtherFile 
verbose: y, force: y, debug: y, in: ./foo/bar/someFile, out: /fizz/someOtherFile 
#!/bin/bash # More safety, by turning some bugs into errors. # Without `errexit` you don’t need ! and can replace # PIPESTATUS with a simple $?, but I don’t do that. set -o errexit -o pipefail -o noclobber -o nounset  # -allow a command to fail with !’s side effect on errexit # -use return value from ${PIPESTATUS[0]}, because ! hosed $? ! getopt --test > /dev/null  if [[ ${PIPESTATUS[0]} -ne 4 ]]; then     echo 'I’m sorry, `getopt --test` failed in this environment.'     exit 1 fi  OPTIONS=dfo:v LONGOPTS=debug,force,output:,verbose  # -regarding ! and PIPESTATUS see above # -temporarily store output to be able to check for errors # -activate quoting/enhanced mode (e.g. by writing out “--options”) # -pass arguments only via   -- "$@"   to separate them correctly ! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") if [[ ${PIPESTATUS[0]} -ne 0 ]]; then     # e.g. return value is 1     #  then getopt has complained about wrong arguments to stdout     exit 2 fi # read getopt’s output this way to handle the quoting right: eval set -- "$PARSED"  d=n f=n v=n outFile=- # now enjoy the options in order and nicely split until we see -- while true; do     case "$1" in         -d|--debug)             d=y             shift             ;;         -f|--force)             f=y             shift             ;;         -v|--verbose)             v=y             shift             ;;         -o|--output)             outFile="$2"             shift 2             ;;         --)             shift             break             ;;         *)             echo "Programming error"             exit 3             ;;     esac done  # handle non-option arguments if [[ $# -ne 1 ]]; then     echo "$0: A single input file is required."     exit 4 fi  echo "verbose: $v, force: $f, debug: $d, in: $1, out: $outFile" 
vote vote

73

#!/bin/bash  while [[ "$#" -gt 0 ]]; do     case $1 in         -t|--target) target="$2"; shift ;;         -u|--uglify) uglify=1 ;;         *) echo "Unknown parameter passed: $1"; exit 1 ;;     esac     shift done  echo "Where to deploy: $target" echo "Should uglify  : $uglify" 
./deploy.sh -t dev -u  # OR:  ./deploy.sh --target dev --uglify 
vote vote

69

#!/bin/bash for i in "$@" do case $i in     -p=*|--prefix=*)     PREFIX="${i#*=}"      ;;     -s=*|--searchpath=*)     SEARCHPATH="${i#*=}"     ;;     -l=*|--lib=*)     DIR="${i#*=}"     ;;     --default)     DEFAULT=YES     ;;     *)             # unknown option     ;; esac done echo PREFIX = ${PREFIX} echo SEARCH PATH = ${SEARCHPATH} echo DIRS = ${DIR} echo DEFAULT = ${DEFAULT} 
vote vote

55

while [ "$#" -gt 0 ]; do   case "$1" in     -n) name="$2"; shift 2;;     -p) pidfile="$2"; shift 2;;     -l) logfile="$2"; shift 2;;      --name=*) name="${1#*=}"; shift 1;;     --pidfile=*) pidfile="${1#*=}"; shift 1;;     --logfile=*) logfile="${1#*=}"; shift 1;;     --name|--pidfile|--logfile) echo "$1 requires an argument" >&2; exit 1;;          -*) echo "unknown option: $1" >&2; exit 1;;     *) handle_argument "$1"; shift 1;;   esac done 

Questions similaires