shell 处理用户输入

处理用户输入


传递参数

#!/bin/bash
# Adding command-line parameters

if [ $# -ne 2 ] 
then
     echo Usage: $(basename $0) parameter1 parameter2
else
     total=$[ $1 + $2 ]
     echo $1 + $2 is $total
fi
exit

读取参数

$0 对应脚本名,$1 对应第一个命令行参数,$2 对应第二个命令行参数,以此类推,直到$9

#!/bin/bash
# Using one command-line parameter
factorial=1
for (( number = 1; number <= $1; number++ ))
do
     factorial=$[ $factorial * $number ]
done
echo The factorial of $1 is $factorial
exit

# Using two command-line parameters
product=$[ $1 * $2 ]
echo The first parameter is $1.
echo The second parameter is $2.
echo The product value is $product.
exit

参数之间是以空格分隔的,所以 shell 会将字符串包含的空格视为两个参数的分隔符。 要想在参数值中加入空格,必须使用引号(单引号或双引号均可)

#!/bin/bash
# Using one command-line string parameter

echo Hello $1, glad to meet you.
exit 

将文本字符串作为参数传递时,引号并不是数据的一部分,仅用于表明数据的起止位置

如果脚本需要的命令行参数不止 9 个,则仍可以继续加入更多的参数,但是需要稍微修改一 下位置变量名。在第 9 个位置变量之后,必须在变量名两侧加上花括号,比如${10}

#!/bin/bash
# Handling lots of command-line parameters

product=$[ ${10} * ${11} ]
echo The tenth parameter is ${10}.
echo The eleventh parameter is ${11}.
echo The product value is $product.
exit

读取脚本名

basename 命令可以返回不包含路径的脚本名

#!/bin/bash
# Using the $0 command-line parameter in messages

scriptname=$(basename $0)
echo The $scriptname run at $(date) >> $HOME/scripttrack.log
exit

参数测试

在使用位置变量之前一定要检查是否为空

#!/bin/bash
# Using one command-line parameter

if [ -n "$1" ]
then
     factorial=1
     for (( number = 1; number <= $1; number++ ))
     do
          factorial=$[ $factorial * $number ]
     done
     echo The factorial of $1 is $factorial
else
     echo "You did not provide a parameter."
fi
exit 

特殊参数变量

参数统计

特殊变量$#含有脚本运行时携带的命令行参数的个数

#!/bin/bash
# Counting command-line parameters

if [ $# -eq 1 ] 
then
     fragment="parameter was"
else
     fragment="parameters were"
fi
echo $# $fragment supplied.
exit

获取命令行中最后一个参数

#!/bin/bash
# Testing grabbing the last parameter

echo The number of parameters is $#
echo The last parameter is ${!#}
exit

当命令行中没有任何参数时,$#的值即为 0,但${!#}会返回命令行中的脚本名。

获取所有的数据

$*变量和$@变量可以轻松访问所有参数

∗ 变量会将所有的命令行参数视为一个单词。这个单词含有命令行中出现的每一个参数。基本上, *变量会将所有的命令行参数视为一个单词。这个单词含有命令行中出现的每一个参数。 基本上, 变量会将所有的命令行参数视为一个单词。这个单词含有命令行中出现的每一个参数。基本上,*变量会将这些参数视为一个整体,而不是一系列个体。

#!/bin/bash
# Testing different methods for grabbing all the parameters

echo
echo "Using the \$* method: $*"
echo 
echo "Using the \$@ method: $@"
echo 
exit

$@变量会将所有的命令行参数视为同一字符串中的多个独立的单词

#!/bin/bash
# Exploring different methods for grabbing all the parameters

echo
echo "Using the \$* method: $*"
count=1
for param in "$*"
do
     echo "\$* Parameter #$count = $param"
     count=$[ $count + 1 ]
done

echo 
echo "Using the \$@ method: $@"
count=1
for param in "$@"
do
     echo "\$@ Parameter #$count = $param"
     count=$[ $count + 1 ]
done
echo 
exit

$*变量会将所有参数视为单个参数,而$@变量会单独处理每个参数

这里再详细说明一下$*$@的区别。当$*出现在双引号内时,会被扩展成由多个命令行参数组成的单个单词,每 个参数之间以 IFS 变量值的第一个字符分隔,也就是说,$*会被扩展"$1c 2 c . . " ( 其中 c 是 I F S 变量值的第一个字符 ) 。当 ‘ 2c.."(其中 c 是 IFS 变量值 的第一个字符)。当` 2c.."(其中cIFS变量值的第一个字符)。当@出现在双引号内时,其所包含的各个命令行参数会被扩展成独立的单词,也就是说,$@`会被扩展为"$1"“$2”

移动参数

在使用 shift 命令时,默认情况下会将每个位置的变量值都向左移动一个位置。因此,变 量$3 的值会移入$2,变量$2 的值会移入$1,而变量$1 的值则会被删除(注意,变量$0 的值, 也就是脚本名,不会改变)。

#!/bin/bash
# Shifting through the parameters

echo 
echo "Using the shift method:"
count=1
while [ -n "$1" ]
do
     echo "Parameter #$count = $1"
     count=$[ $count + 1 ]
     shift
done
echo 
exit

使用 shift 命令时要小心。如果某个参数被移出,那么它的值就被丢弃了,无法再恢复。

也可以一次性移动多个位置。只需给 shift 命令提供一个参数,指明要移动的位置 数即可

#!/bin/bash
# Shifting mulitiple positions through the parameters

echo 
echo "The original parameters: $*"
echo "Now shifting 2..."
shift 2
echo "Here's the new first parameter: $1"
echo
exit

处理选项

查找选项

处理简单选项

#!/bin/bash
# Extract command-line options

echo 
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 an option" ;;
     esac
     shift
done
echo 
exit

分离参数和选项

#!/bin/bash
# Extract command-line options and parameters

echo 
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
              break;;
          *) echo "$1 is not an option" ;;
     esac
     shift
done
#
echo
count=1
for param in $@
do
     echo "Parameter #$count: $param"
     count=$[ $count + 1 ]
done
echo 
exit

处理含值的选项

#!/bin/bash
# Extract command-line options and values

echo 
while [ -n "$1" ]
do
     case "$1" in
          -a) echo "Found the -a option" ;;
          -b) param=$2 
              echo "Found the -b option with parameter value $param" 
              shift;;
          -c) echo "Found the -c option" ;;
          --) shift
              break;;
          *) echo "$1 is not an option" ;;
     esac
     shift
done
#
echo
count=1
for param in $@
do
     echo "Parameter #$count: $param"
     count=$[ $count + 1 ]
done
exit

使用getopt命令

getopt optstring parameters

#!/bin/bash
# Extract command-line options and values with getopt

set -- $(getopt -q ab:cd "$@")

echo 
while [ -n "$1" ]
do
     case "$1" in
          -a) echo "Found the -a option" ;;
          -b) param=$2 
              echo "Found the -b option with parameter value $param" 
              shift;;
          -c) echo "Found the -c option" ;;
          --) shift
              break;;
          *) echo "$1 is not an option" ;;
     esac
     shift
done

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

使用getopts命令

getopts optstring variable

#!/bin/bash
# Extract command-line options and values with getopts

echo 
while getopts :ab:c opt
do
     case "$opt" in
          a) echo "Found the -a option" ;;
          b) echo "Found the -b option with parameter value $OPTARG";;
          c) echo "Found the -c option" ;;
          *) echo "Unknown option: $opt" ;;
     esac
done
exit

获取用户输入

基本的读取

read 命令从标准输入(键盘)或另一个文件描述符中接受输入。获取输入后,read 命令会 将数据存入变量。

#!/bin/bash
# Using the read command with REPLY variable

read -p "Enter your name: "
echo
echo "Hello $REPLY, welcome to my script."
exit

超时

使用 read 命令时要当心。脚本可能会一直苦等着用户输入。如果不管是否有数据输入,脚 本都必须继续执行,你可以用-t 选项来指定一个计时器。-t 选项会指定 read 命令等待输入的 秒数。如果计时器超时,则 read 命令会返回非 0 退出状态码

#!/bin/bash
# Using the read command with a timer

if read -t 5 -p "Enter your name: " name
then
     echo "Hello $name, welcome to my script."
else
     echo
     echo "Sorry, no longer waiting for name."
fi
exit

无显示读取

-s 选项可以避免在 read 命令中输入的数据出现在屏幕上(其实数据还是会被显示,只不 过 read 命令将文本颜色设成了跟背景色一样)。

#!/bin/bash
# Hiding input data

read -s -p "Enter your password: " pass
echo
echo "Your password is $pass"
exit

从文件中读取

#!/bin/bash
# Using the read command to read a file

count=1
cat $HOME/scripts/test.txt | while read line
do
     echo "Line $count: $line"
     count=$[ $count + 1 ]
done
echo "Finished processing the file."
exit

实战

该脚本在处理用户输入的同时,使用 ping 命令或 ping6 命令 来测试与其他网络主机的连通性

#!/bin/bash
# Check systems on local network
# allowing for a variety of input
# methods.


########### Determine Input Method ###################


# Check for command-line options here using getopts. 
# If none, then go on to File Input Method

while getopts t: opt 
do
     case "$opt" in
          t) # Found the -t option 
             if [ $OPTARG = "IPv4" ]
             then
                  pingcommand=$(which ping)
             
             elif [ $OPTARG = "IPv6" ]
             then
                  pingcommand=$(which ping6)
             
             else
                  echo "Usage: -t IPv4 or -t IPv6"
                  echo "Exiting script..."
                  exit
             fi
             ;;
          *) echo "Usage: -t IPv4 or -t IPv6"
             echo "Exiting script..."
             exit;;
     esac
     
     shift $[ $OPTIND - 1 ]
     
     if [ $# -eq 0 ]
     then
          echo
          echo "IP Address(es) parameters are missing."
          echo
          echo "Exiting script..."
          exit
     fi

     for ipaddress in "$@"
     do
          echo
          echo "Checking system at $ipaddress..."
          echo
          $pingcommand -q -c 3 $ipaddress
          echo
     done
     exit
done

########### File Input Method ###################

echo
echo "Please enter the file name with an absolute directory reference..."
echo
choice=0
while [ $choice -eq 0 ] 
do
     read -t 60 -p "Enter name of file: " filename
     if [ -z $filename ]
     then
          quitanswer=""
          read -t 10 -n 1 -p "Quit script [Y/n]? " quitanswer
          #
          case $quitanswer in 
          Y | y) echo
                 echo "Quitting script..."
                 exit;;
          N | n) echo
                 echo "Please answer question: "
                 choice=0;;
          *)     echo 
                 echo "No response. Quitting script..."
                 exit;;
          esac
     else
          choice=1
     fi
done

if [ -s $filename ] && [ -r $filename ]
     then
          echo "$filename is a file, is readable, and is not empty."
          echo
          cat $filename | while read line
          do
               ipaddress=$line
               read line
               iptype=$line
               if [ $iptype = "IPv4" ]
               then
                    pingcommand=$(which ping)
               else
                    pingcommand=$(which ping6)
               fi
               echo "Checking system at $ipaddress..."
               $pingcommand -q -c 3 $ipaddress
               echo
          done
          echo "Finished processing the file. All systems checked."
     else
          echo 
          echo "$filename is either not a file, is empty, or is"
          echo "not readable by you. Exiting script..."
fi 
#################### Exit Script #####################
exit

小结

本章展示了从脚本用户处获取数据的 3 种方法。命令行参数允许用户运行脚本时直接在命令 行中输入数据。脚本可通过位置变量获取命令行参数。

shift 命令通过对位置变量进行轮转(rotating)的方式来操作命令行参数。就算不知道参 数的数量,也可以轻松遍历所有参数。

有 3 个特殊变量可以用来处理命令行参数。shell 会将KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲变量设为命令行参数的个数。*变 量会将所有命令行参数保存为一个字符串。$@变量会将所有命令行参数保存为独立的单词。这些 变量在处理参数列表时非常有用。

除了命令行参数,还可以通过命令行选项向脚本传递信息。命令行选项是以连字符起始的单 个字母。可以使用不同选项改变脚本的行为。

bash shell 提供了 3 种方法来处理命令行选项。第一种方法是将其像命令行参数一样处理。利 用位置变量遍历选项并进行相应的处理。第二种方法是使用 getopt 将命令行选项和参数转换成 可以在脚本中处理的标准格式。最后一种方法是使用拥有更多高级功能的 getopts 命令。

read 命令能够以交互式方法从脚本用户处获得数据。该命令允许脚本向用户询问并等待用 户回答。read 命令会将脚本用户输入的数据存入一个或多个变量,以方便在脚本中使用。

read 命令有一些选项支持自定义脚本的输入数据,比如不显示用户输入、超时选项以及限 制输入的字符数量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值