14 Linux processing user input shell script

Article directory

    • 14. Handling User Input
      • 14.1 Command line parameters
      • 14.2 Special parameter variables
      • 14.3 Moving variables
      • 14.4 Processing options
      • 14.5 Option Standardization
      • 14.6 Getting User Input

14. Handle user input

14.1 Command line parameters

Pass two parameters to addem 10 30

./addem 10 30

Read position parameters:$0 is the program name, $1 to $9 are the first to ninth parameters , the following parameters need to be ${10}. Parameters are separated by spaces.

#!/bin/bash
#Realize parameter reading and multiplication
total=$[ $1 * $2 ]
echo "The first param is $1"
echo "The second param is $2"
echo "The total value is $total"

echo "The second param is ${10}"

Read script name:$0 passes the complete script path, use basename to get the script name without the path, so as to realize different functions according to different script names.

#!/bin/bash
#Get the path name and script name of the script
path_name=$0
script_name=$(basename $0)

echo "The path of script is $path_name"
echo "The script name is $script_name"

Test parameters: If the script is run without parameters, an error message will be generated, so it is best to add relevant parameter tests
Error message description
Use -n to test whether there is data in the parameter

#!/bin/bash
#Check whether parameter 1 is normal input parameter
if [ -n "$1" ]
then
  echo "The first parameter you entered is $1 "
else
  echo "You did not enter any parameters"
the fi

14.2 Special parameter variables

Parameter Statistics
Some record command line parameters related variables, such as $# is the total number of record command line parameters

#!/bin/bash
#Test the total number of parameters, if there are two, do addition, otherwise an error will be reported
if [ $# -ne 2 ]
then
  echo "Usage: $(basename $0) a b"
  echo
else
  total=$[ $1 + $2 ]
  echo
  echo "The total is $total"
  echo
the fi

Since $# records the total number, then ${$#} should represent the last command line parameter, but this is not the case, ${! #} is the correct way to get the last parameter variable.

#!/bin/bash
#Test to get the last parameter
echo "The last param is ${$#}"
echo "The last param is ${<!-- -->!#}"

run result

Crawl all data
$*: All parameters are combined into a whole string
$@: a separate string providing all parameters

#!/bin/bash
# test $* and $@
count=1
for param in $*
  echo "\$* parameter #$count = $param"
  count=$[ $count + 1 ]
done

count=1
for param in $@
do
  echo "\$@parameter #$count = $param"
  count=$[ $count + 1 ]
done

operation result:
test
It seems to be different from what we introduced, well, note that we wrote when traversing:

for param in $@

The difference between $* and $@ can only be from "$*" and "$@" look out, i.e. write doing

for param in "$*"
for param in "$@"

The final execution result is
real result

14.3 Moving variables

When you don’t know how many parameters there are, you can use shift to transfer the value of the subsequent variable to the previous one, such as transferring $2 to $1, while $1 is destroyed.

#!/bin/bash
#simple test shift
count=1
while [ -n "$1" ]
do
  echo "Parameter #$count = $1"
  count=$[ $count + 1 ]
  shift
done

Note that shift n indicates how many parameters to move

14.4 Processing options

Handle simple options
Use case to extract parameters and determine whether it is an option

#!/bin/bash
#Use shift to determine whether each parameter is an option in turn
count=1
while [ -n "$1" ]
do
  case "$1" in
  -a) echo "Found the -a option" ;;
  -b) echo "Found the -b option" ;;
  -c) echo "Found the -c option" ;;
   *) echo "$1 is not the option" ;;
  esac
  shift
done

operation result:
run result
Separate parameters and options
If a script uses both parameters and options, a special parameter is needed at this time to help identify which are parameters and which are options, here use “–” to separate.

#!/bin/bash
#processing options
count=1
while [ -n "$1" ]
do
  case "$1" in
  -a) echo "Found the -a option" ;;
  -b) echo "Found the -b option" ;;
  -c) echo "Found the -c option" ;;
  --) shift #just to skip -- this parameter
      break;;
   *) echo "$1 is not the option" ;;
  esac
  shift
done

#Process parameters
count=1
for param in "$@"
do
  echo "Parameter #$count: $param"
  count=$[ $count + 1 ]
done

Results of the:
execution result
Handle options with values
For example, in the following example, test1 should serve the option -a

./testing.sh -a test1 -b -c -d test2

You only need to insert relevant statements for reading parameters in the corresponding options

#!/bin/bash
#processing options
count=1
while [ -n "$1" ]
do
  case "$1" in
  -a) echo "Found the -a option" ;;
  -b) param="$2" #Read the parameters after -b
      echo "Found the -b option with the param $param"
      shift;; #skip this parameter after -b
  -c) echo "Found the -c option" ;;
  --) shift #just to skip -- this parameter
      break;;
   *) echo "$1 is not the option" ;;
  esac
  shift
done

#Process parameters
count=1
for param in "$@"
do
  echo "Parameter #$count: $param"
  count=$[ $count + 1 ]
done

operation result
Run result
The above command can only handle a single option, and has no ability to compound options, so the following getopt command is introduced

14.5 Option Standardization

getopt command
The format of the getopt command is as follows

getopt optstring parameters

optstring lists each command-line option letter you want to use in the script. Then, append a colon after each option letter that requires a parameter value. The getopt command parses the provided arguments based on the optstring you define.
For example:

#ab:cd indicates that there are 4 options, among which b needs to have parameters
 $getopt ab:cd -a -b test1 -cd test2 test3
 -a -b test1 -c -d --test2 test3

If an undeclared parameter is used

$getopt ab:cd -a -b test1 -cde test2 test3
getopt: invalid option --e
 -a -b test1 -c -d --test2 test3

You can use -q to ignore this parameter

$getopt -q ab:cd -a -b test1 -cde test2 test3
 -a -b 'test1' -c -d -- 'test2' 'test3'

Using getopt in scripts
Think about it carefully, use getopt to get formatted input. But when executing in a script, I cannot execute the script with formatted input as input. So we use set --, which will replace the original command with the formatted command.

#!/bin/bash
#Process the input command, compared with the previous example code, only the following line is added
set -- $(getopt -q ab:cd "$@")
#processing options
count=1
while [ -n "$1" ]
do
  case "$1" in
  -a) echo "Found the -a option" ;;
  -b) param="$2" #Read the parameters after -b
      echo "Found the -b option with the param $param"
      shift;; #skip this parameter after -b
  -c) echo "Found the -c option" ;;
  --) shift #just to skip -- this parameter
      break;;
   *) echo "$1 is not the option" ;;
  esac
  shift
done

#Process parameters
count=1
for param in "$@"
do
  echo "Parameter #$count: $param"
  count=$[ $count + 1 ]
done

operation result
execution result
But there is still a problem with this code, which cannot properly handle parameter values with spaces and quotes
question
Use more advanced optgets
getopts command format:

 getopts optstring variable

optstring value:
Valid option letters are listed in optstring, and a colon is added if the option letter requires a parameter value. To get rid of the error message, put a colon before optstring.

getopts command:
Save the current arguments in a variable defined on the command line.

Two important environment variables
The OPTARG environment variable will save the parameter value after the option.

The OPTIND environment variable holds the parameter position in the parameter list that getopts is processing. This way you can continue processing other command line arguments after processing the options.

Sample code:

#!/bin/bash
#Use getopts to get the option parameter segmentation, note that the option under the case is not -a), and the position transfer is realized after traversing all the parameters
while getopts :ab:cd opt
do
   case "$opt" in
   a) echo "This is -a option";;
   b) echo "This is -b option with value $OPTARG";;
   c) echo "This is -c option";;
   d) echo "This is -d option";;
   *) echo "Unknown option:$opt" ;;
   esac
done

#Skip the currently processed parameters
shift $[ $OPTIND - 1 ]

#Loop through parameters
count=1
for param in "$@"
do
   echo "Parameter $count: $param"
   count=$[ $count + 1 ]
done

Option Standardization:
Linux commands already have specific meanings for key parameters, refer to
options

14.6 Get user input

Basic Read
Use read to get variable value from standard input

#!/bin/bash
#-n means to get input without wrapping
echo -n "Enter your name:"
read name
echo "Hello $name, welcome to my program."

#read -p can output some prompt information to get a single input
read -p "Please enter your age: " age
days=$[ $age * 365 ]
echo "That makes you over $days days old;"

#read get multiple inputs
read -p "Please enter your first and last: " first last
echo "Checking data for $first, $last..."

#If no variable is specified, all input will be saved in REPLY
read -p "Enter the name which will save in:"
echo "hello, welcome to $REPLY"

Timeout judgment
In order to prevent waiting all the time, use -t to set the number of seconds to wait, and return a non-zero exit code after timeout.
You can also set -n num to read the specified number of inputs and exit.

#!/bin/bash
#Set the input of the timeout
if read -t 5 -p "Please enter your name:" name
then
   echo "Hello $name, welcome to my script"
else
   echo "Sorry, too slow!"
the fi
#Set the specified number of inputs

read -n1 -p "DO you want to continue [Y/N]?" answer
case $answer in
   Y | y) echo "fine, continue on...";;
   N | n) echo "OK, goodbye"
          exit;;
esac
echo "This is the end of the script"

Result
Read in hidden mode
The -s option can prevent the data entered in read from appearing on the display

#!/bin/bash
read -s -p "Enter your password: " pass
echo
echo "Is your password really $pass?"

Read from file

#!/bin/bash
# reading data from a file
#
count=1
cat test | while read line
do
   echo "Line $count: $line"
   count=$[$count + 1]
done
echo "Finished processing the file"