脚本输入处理——获得用户输入

脚本输入处理

获得用户输入

在一个交互式的Shell脚本中,一般使用read命令来获取用户输入。

基本的读取

read命令比较常用的语法格式:


read [-p prompt] [var1 var2...]

-p选项用于在尝试读取任何输入之前,显示提示信息(prompt)的内容到标准输出。一般情况用来提示用户输入哪些输入信息。

read命令会每次从标准输入读取一行的内容(-u可以指定文件描述符),将第一个单词赋值给第一个变量var1,第二个赋值给var2.......。如果输入的单次数少于指定的变量数,那么剩下的会被设置为空。IFS全局环境变量可以设置输入内容之间的分割符,默认为空格。

如:

[root@rs1 read]# cat read_1.sh 
#!/bin/bash

#提示用户输入用户名,然后将用户的输入赋值给变量username
read -p "Enter your name,please: " username

#提示用户输入电话号码,然后赋值给变量email
read -p "Enter your tel number,please: " tel

#询问用户是否继续,提示输入y或n,然后将用户输入的内容赋值给input
read -p "Are your sure to contuinue?[y/n]" input

case $input in
    #如果输入为y或者Y,则显示用户名和电话到标准输出
    y|Y)
        echo "Your name is : $username"
        echo "Your tel number is : $tel "
    ;;
    [nN]*)
        echo "Bye"
        exit
    ;;
    *)
        echo "Just input y or n,please"
        exit 1
    ;;
esac

执行脚本:


[root@rs1 read]# bash read_1.sh     
Enter your name,please: fsx
Enter your tel number,please: 123
Are your sure to contuinue?[y/n]y
Your name is : fsx
Your tel number is : 123    

[root@rs1 read]# bash read_1.sh 
Enter your name,please: fsx
Enter your tel number,please: 123
Are your sure to contuinue?[y/n]n
Bye

[root@rs1 read]# bash read_1.sh 
Enter your name,please: fsx
Enter your tel number,please: 123
Are your sure to contuinue?[y/n]Nsd
Bye

[root@rs1 read]# bash read_1.sh 
Enter your name,please: fsx
Enter your tel number,please: 123
Are your sure to contuinue?[y/n]ttt     //参数输入错误的情况
Just input y or n,please

输入超时

可以使用read的-t选项来设置read命令读取用户输入得超时时间。如果在指定的时间内没有读入一行输入(即没有回车),read命令就会返回一个失败。

如:(还是上面的脚本代码,仅仅添加了-t选项)

[root@rs1 read]# cat read_2.sh 
#!/bin/bash

#提示用户输入用户名,然后将用户的输入赋值给变量username
read -t 7 -p "Enter your name,please: " username

#提示用户输入电话号码,然后赋值给变量email
read -t 5 -p "Enter your tel number,please: " tel

#询问用户是否继续,提示输入y或n,然后将用户输入的内容赋值给input
read -t 5 -p "Are your sure to contuinue?[y/n]" input

case $input in
    #如果输入为y或者Y,则显示用户名和电话到标准输出
    y|Y)
        echo "Your name is : $username"
        echo "Your tel number is : $tel "
    ;;
    [nN]*)
        echo "Bye"
        exit
    ;;
    *)
        echo "Just input y or n,please"
        exit 1
    ;;
esac

执行脚本:


[root@rs1 read]# bash read_2.sh     //正确输入
Enter your name,please: fsx
Enter your tel number,please: 123
Are your sure to contuinue?[y/n]y
Your name is : fsx
Your tel number is : 123    

[root@rs1 read]# bash read_2.sh     //输入超时
Enter your name,please: Enter your tel number,please: Are your sure to contuinue?[y/n]Just input y or n,please

拒绝回显输入

read命令可以使用-s选项隐藏用户的输入。如果指定了-s,则来自终端的输入不会回显,这对于用户密码等隐私相关的验证有一定的安全意义。

如:

[root@rs1 read]# cat read_3.sh 
#!/bin/bash

#定义变量password
password=''

#显示提示输入密码的信息到标准输出
echo "Enter your password: "

#使用while循环隐式地从标准输入每次读取一个字符,且反斜杠不做转义
#将读取的字符赋值给变量char
while IFS= read -r -s -n1 char
do
    #如果读入的字符为空(直接输出的空格),则退出while循环
    if test -z $char
    then
        echo
        break
    fi
    #如果输入的是backspace,则从变量password中移除最后一个字符
    #并向左删除一个*
    #否则,将变量char的值累加赋值给password变量
    if [[ $char == $'\x08' ]]
    then
        #从变量password中移除最后一个字符
        [[ -n $password ]] && password=${password:0:${#password}-1}
        #并向左删除一个*
        printf '\b \b'
    else
        #将变量char的值累加赋值给变量password
        password+=$char
        #打印一个星号
        printf "*"
    fi
done

echo "Password is : $password"

执行脚本:


[root@rs1 read]# bash read_3.sh 
Enter your password: 
***
Password is : fsx

从文件中读取

read命令从文件读取数据的方法主要有两种。一种是在while循环或until循环中使用read命令,通过文件描述符一行一行地读取文件内容。另一种是在for循环中使用cat <filename>来读取文件的内容。

在for循环中使用cat <filename>读取文件的语法:


for data in $(cat <filemae>)
do
    command1
    command2
    ...
done    

filename代表一个文本文件,读取的内容回被存入便来嗯data,此变量会在for循环中使用,来对读入的数据进行处理。

如果要按逐行读取文件内容时,要设置IFS的值为\n

如:


[root@rs1 read]# cat read_4.sh ;
#!/bin/bash

#使用变量O_IFS来保存环境变量IFS的值
old_IFS=$IFS

#如果指定的命令行参数个数不为1,则显示脚本使用方法,并退出运行
if test $# -ne 1
then
    #显示脚本的使用方法信息
    echo "Usage: `basename $0` filename"
    #退出脚本
    exit 2
fi

#如果指定文件不存在,则显示提示信息,并退出脚本的执行,退出状态码为1
if test ! -f $filename
then
    #提示文件不存在
    echo "The file $filename does not exist!"
    #退出
    exit 1
fi

#修改环境变量IFS值,使得for循环里面按行读取文件内容
IFS=$'\n'

for line in $(cat $1)
do
    echo "$line"
    echo "tag#######################################"
done
#恢复IFS的值
IFS=old_IFS

执行脚本:

  • 如果没有执行参数

    
    [root@rs1 read]# bash read_4.sh 
    Usage: read_4.sh filename
  • 如果文件不存在

    
    [root@rs1 read]# bash read_4.sh 1
    The file  does not exist!
  • 如果文件存在

    
    [root@rs1 read]# bash read_4.sh 1
    #
    tag#######################################
    # /etc/fstab
    tag#######################################
    # Created by anaconda on Tue May 22 08:52:29 2018
    tag#######################################
    #
    tag#######################################
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    tag#######################################
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    tag#######################################
    #
    tag#######################################
    /dev/mapper/rhel-root   /                       xfs     defaults        1 1
    tag#######################################
    UUID=35ae0b8d-9734-4f72-8a4c-1ae16123f407 /boot                   xfs     defaults        1 2
    tag#######################################
    /dev/mapper/rhel-swap   swap                    swap    defaults        0 0
    tag#######################################

while的副作用:当读取每行内容会去掉重复的空格和制表符,即会消除每行的原本格式。

for循环结合IFS保留了原本的格式。

总结

  1. 可以使用函数传递命令行参数的方法,向Shell脚本传递参数。传递的命令行参数存储在位置参数{$1,$2,$3...${10}...}

  2. 特殊变量"$*"和"$@"会存储所有传递的命令行参数,"$#"会存储传递的命令行参数的个数

  3. 当只接受一个参数时,使用case命令比较合适。case常见于Linux下的应用程序或服务的启动脚本中

  4. case语句中的每个模式匹配时大小写敏感的,可以使用"shopt -s nocasematch"开启nocasematch选项

  5. 当使用多个命令行参数时,可以使用shift命令在一个变量中一个接一个的获取命令行参数

  6. shift时Bash的一个内部命令。此命令用于将传递的参数变量左移,每次移动,$1和$#都会因之改变

  7. 为了使得Shell脚本严谨,在脚本开头一般会编写一段与脚本环境或变量进行检查的代码

  8. getopts和getopt时更为专业的解析命令行选项和参数的工具

  9. read命令的-p选项用于显示提示信息到标准错误里面

  10. read命令的-t选项可以用来设置用户的输入超时时长

  11. read命令的-s选项,可以设置输入不回显

  12. 使用read读取文件中数据的方式有两种:while/until循环;for循环。使用for循环时注意IFS的值

猜你喜欢

转载自blog.csdn.net/fsx2550553488/article/details/80973185