Bash Script with Parsing Argument in Linux

2020-03-30 04:34发布

问题:

I want to write a bash script :

schedsim.sh [-h] [-c x] -i pathfile

Where :

• -h: print the current username.

• -c x : get an option-argument x and print out (x + 1). If no argument was found, print the default value is 1.

• -i pathfile: print the size of pathfile. The pathfile is a required argument. If no argument was found, print out an error message.

This is what I've done so far :

x=""
path=""
while getopts ":hc:i:" Option
do
case $Option in
h) echo -e "$USER\n"
;;
c) x=$optarg+1
;;
i) path=$(wc -c <"$optarg")
;;
esac
done

if [ -z "$x"] 
then
 echo -e "$x\n"
else
 echo 1
fi

if [ -z "$path"] 
then
 echo $path
else
 echo "Error Message"
 exit 1
fi

How to finish the option-argument,required-argument part and the error message part?

回答1:

A rewrite:

while getopts ":hc:i:" Option; do
    case $Option in
        h)  echo "$USER"
            ;;
        c)  x=$(($OPTARG + 1))
            ;;
        i)  if [[ -f $OPTARG ]]; then
                size=$(wc -c <"$OPTARG")
            else
                echo "error: no such file: $OPTARG"
                exit 1
            fi 
            ;;
    esac
done

if [[ -z $x ]]; then
    echo "you used -c: the result is $x"
fi

if [[ -z $size ]]; then
    echo "you used -i: the file size is $size"
fi

Notes:

  • OPTARG must be in upper case.
  • you need $((...)) for bash arithmetic
  • check that the file exists before using it
  • use a sensible filename (path does not represent the size of a file)
  • there must be a space before ]
  • echo -e "value\n" is too much work: you just want echo "value" unless you want to process escape sequences in the value:

    $ var="foo\tbar\rbaz"
    $ echo "$var"
    foo\tbar\rbaz
    $ echo -e "$var\n"
    baz bar
    
    $ 
    

Update: responding to comments: simplified and more complete option handling; expanded error handling.

#!/bin/bash
declare -A given=([c]=false [i]=false)
x=0
path=""

while getopts ":hc:i:" Option; do
    case $Option in
        h)  echo "$USER"
            ;;
        c)  x=$OPTARG
            given[c]=true
            ;;
        i)  path=$OPTARG
            given[i]=true
            ;;
        :)  echo "error: missing argument for option -$OPTARG"
            exit 1
            ;;
        *)  echo "error: unknown option: -$OPTARG"
            exit 1
            ;;
    esac
done

# handle $x
if [[ ! $x =~ ^[+-]?[[:digit:]]+$ ]]; then
    echo "error: your argument to -c is not an integer"
    exit 1
fi
if ! ${given[c]}; then
    printf "using the default value: "
fi
echo $(( 10#$x + 1 ))

# handle $path
if ! ${given[i]}; then
    echo "error: missing mandatory option: -i path"
    exit 1
fi
if ! [[ -f "$path" ]]; then
    echo "error: no such file: $path"
    exit 1
fi
echo "size of '$path' is $(stat -c %s "$path")"


回答2:

I think what you're looking for is "argument parsing" in bash. Please take a look at this excellent answer: https://stackoverflow.com/a/14203146/3380671

Regarding this required/optional part: initialize the variable with an empty string and just check the string's length after the argument parsing.

FILE_PATH=""
# Do the argument parsing here ...
# And then:
if [ -z "$FILE_PATH" ]
then
  echo "Please specify a path. Aborting."
  exit 1
fi