文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Shell脚本read用法实现

2023-01-12 10:46

关注
目录

1.概述

到目前为止,编写的脚本都缺少一个常用于大多数计算机程序的特性–交互性,或者说与用户互动的能力。尽管很多程序并不需要是交互式的,但能够直接接受用户输入,确实有利于某些程序。

2. read从标准输入读取值

内建命令read可用于从标准输入中读取一行。该命令可以读取键盘输入,如果使用了重定向,也可以读取文件的数据行。该命令用法如下:

read [-options] [variable...]

其中,option是一个或多个选项,variable是一个或多个变量,用于保存输入值。如果未指定变量,则输入值保存在Shell变量REPLAY中。使用read命令改写之前的整数验证脚本:

#!/bin/bash

# read-integer

echo -n "Please enter an integer -> "
read int

if [[ "$int" =~ ^-?[0-9]+$ ]]; then
        if [ "$int" -eq 0 ]; then
                echo "$int is zero."
        else
                if [ "$int" -lt 0 ]; then
                        echo "$int is negative."
                else
                        echo "$int is positive"
                fi
        fi
        if [ $((int % 2)) -eq 0 ]; then
                echo "$int is even."
        else
                echo "$int is odd."
        fi
else
        echo "Input value is not an integer." >&2
        exit 1
fi

read也可以将输入赋给多个变量

[sysadmin@ansible bin]$ cat read1
#!/bin/bash

#read-multiple

echo -n "Enter one or more values > "
read var1 var2 var3 var4 var5

echo "var1 = '$var1'"
echo "var2 = '$var2'"
echo "var3 = '$var3'"
echo "var4 = '$var4'"
echo "var5 = '$var5'"
[sysadmin@ansible bin]$ read1
Enter one or more values > 1 2 3 4 5
var1 = '1'
var2 = '2'
var3 = '3'
var4 = '4'
var5 = '5'

如果read接收到的值数量少于预期,则多出的变量为空值,如果数量多于预期,则额外的输入全部保存在最后一个变量中。

[sysadmin@ansible bin]$ cat read1
#!/bin/bash

#read-multiple

echo -n "Enter one or more values > "
read var1 var2 var3 var4 var5

echo "var1 = '$var1'"
echo "var2 = '$var2'"
echo "var3 = '$var3'"
echo "var4 = '$var4'"
echo "var5 = '$var5'"
[sysadmin@ansible bin]$ read1
Enter one or more values > a
var1 = 'a'
var2 = ''
var3 = ''
var4 = ''
var5 = ''
[sysadmin@ansible bin]$ read1
Enter one or more values > a b c d e f g
var1 = 'a'
var2 = 'b'
var3 = 'c'
var4 = 'd'
var5 = 'e f g'
[sysadmin@ansible bin]$

如果没有为read命令指定变量,则所有的输入全部保存在Shell变量REPLY中

[sysadmin@ansible bin]$ cat read2
#!/bin/bash

#read-multiple

echo -n "Enter one or more values > "
read

echo "REPLY = '$REPLY'"
[sysadmin@ansible bin]$ read2
Enter one or more values > a b c d
REPLY = 'a b c d'
[sysadmin@ansible bin]$

2.1 read选项

选项描述
-a array将输入分配给数组(从索引0开始)。
-d delimiter将字符串delimter中的第一个字符(而非换行符)作为输入的结束
-e使用readline处理输入,允许使用和命令行相同的方式编辑输入
-i string如果用户直接按Enter键,使用string作为默认值,需要配合-e选项使用
-n num从输入中读取num个字符,而非读取一整行
-p prompt将字符prompt作为输入提示来显示
-r原始模式,不将反斜线符解释为转义
-s静默模式,在用户输入字符时不回显,该模式适用于输入密码或其他机密信息
-t seconds超时,seconds秒之后终止输入,如果输入超时,read返回非0退出状态值
-u fd从文件描述符fd中读取输入

选项-p

[sysadmin@ansible bin]$ cat read2
#!/bin/bash

#read-single

read -p "Enter one or more values > "

echo "REPLY = '$REPLY'"
[sysadmin@ansible bin]$ read2
Enter one or more values > a
REPLY = 'a'
[sysadmin@ansible bin]$

选项-t和-s

[sysadmin@ansible bin]$ cat readpass
#!/bin/bash

#read-pass

if read -t 10 -sp "Enter password > " passwd; then
    echo -e "\nSecret passphrase = '$passwd'"
else
    echo -e "\nInput timed out" >&2
    exit 1
fi
[sysadmin@ansible bin]$ readpass
Enter password >
Secret passphrase = 'abcdef'
[sysadmin@ansible bin]$

选项-e和-i

[sysadmin@ansible bin]$ cat readdefault
#!/bin/bash

#read-default

read -e -p "What is your user name? " -i $USER
echo "You answered: '$REPLY'"
[sysadmin@ansible bin]$ readdefault
What is your user name? sysadmin
You answered: 'sysadmin'
[sysadmin@ansible bin]$

2.2 IFS

Shell通常会提供给read的输入进行单词分割,这意味着输入行中被一个或多个空白字符分割的多个单词会变成若干独立项,再由read分配给各个变量。Shell变量内部字段分割符(Internal Filed Separator,IFS)控制着此行为。IFS的默认值包含了空格符,制表符,换行符,它们都可用于分割单词。
我们可以调整IFS的值,控制read的输入字段。例如:/etc/passwd文件中的数据行采用冒号作为字段分隔符。将IFS的值改成冒号,就可以使用read读入/etc/passwd的内容并顺利将字段分割存入各个变量。来看下面的实现脚本。

[sysadmin@ansible bin]$ cat read-ifs
#!/bin/bash

# read-ifs

FILE=/etc/passwd

read -p "Enter a user > " user_name

file_info="$(grep "^$user_name:" $FILE)"

if [ -n "$file_info" ]; then
    IFS=":" read user pw uid gid name home shell <<< "$file_info"
    echo "User =      '$user'"
    echo "UID =       '$uid'"
    echo "GID =       '$gid'"
    echo "Full Name =    '$name'"
    echo "Home Dir =    '$home'"
    echo "Shell =      '$shell'"
else
    echo "No such user '$user_name'" >&2
    exit 1
fi
[sysadmin@ansible bin]$ read-ifs
Enter a user > jticnoc
User =     'jticnoc'
UID =      '2099'
GID =      '2099'
Full Name =   ''
Home Dir =   '/home/jticnoc'
Shell =     '/bin/bash'
[sysadmin@ansible bin]$

Shell允许一个或多个变量赋值直接出现在命令之前。这些赋值会修改紧随其后的命令的环境。这种赋值效果是临时的。对环境所作的改动仅限于命令执行期间有效。<<< 标识here string。here string类似于here document,但是更简短,仅由单个字符串组成。

2.3 验证输入

好程序和差程序之间的区别往往在于处理意外情况的能力,而意外情况多以错误输入的形式出现。重要的是,每次程序接收到输入的时候,都要执行此类检查,以防止非法数据。

[sysadmin@ansible bin]$ cat read-validate
#!/bin/bash

#read-validate

invalid_input () {
    echo "Invalid input '$REPLAY'" >&2
    exit 1
}

read -p "Enter a single item > "

# input is null
[[ -z "$REPLY" ]] && invalid_input

# input is multi items
(( "$(echo "$REPLY" |wc -w)" > 1 )) && invalid_input

# input filename is valid
if [[ "$REPLY" =~ ^[-[:alnum:]\._]+$ ]]; then
    echo "'$REPLY' is a valid filename."
    if [[ -e "$REPLY" ]]; then
        echo "And file '$REPLY' exists."
    else
        echo "However, file '$REPLY' does not exist."
    fi

    # input is float
    if [[ "$REPLY" =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then
        echo "'$REPLY' is a floating point number."
    else
        echo "'$REPLY' is not a floating point number."
    fi

    # input is int
    if [[ "$REPLY" =~ ^-?[[:digit:]]+$ ]]; then
        echo "'$REPLY' is an integer."
    else
        echo "'$REPLY' is not an integer."
    fi
else
    echo "The string '$REPLY' is not a valid filename."
fi
[sysadmin@ansible bin]$

2.4 菜单

菜单驱动是一中常见的交互方式,菜单驱动的程序会为用户呈现一系列的选项,要求用户从中选择。

[sysadmin@ansible bin]$ cat read-menu
#!/bin/bash

#read-menu

clear
echo "
Please Select:

1.Display System Information
2.Display Disk Space
3.Display Home Space Utilization
4.Quit
"
read -p "Enter selection [0-3] > "

if [[ "$REPLY" =~ ^[0-3]$ ]]; then
    if [[ "$REPLY" == 0 ]]; then
        echo "Program terminated."
        exit
    fi

    if [[ "$REPLY" == 1 ]]; then
        echo "Hostname: $HOSTNAME"
        uptime
        exit
    fi

    if [[ "$REPLY" == 2 ]]; then
        df -h
        exit
    fi

    if [[ "$REPLY" == 3 ]]; then
        if [[ "$(id -u)" -eq 0 ]]; then
            echo "Home Space Utilization (ALL Users)"
            du -sh /home/*
        else
            echo "Home Space Utilizaion ($USER)"
            du -sh "$HOME"
        fi
        exit
    fi
else
    echo "Invalid entry." >&2
    exit 1
fi

第一部分展示了菜单并获取用户输入,第二部分识别输入并执行相应的菜单项功能。注意脚本中exit命令的用法,在完成用户选定的功能后,exit可以防止继续执行不必要的代码。

到此这篇关于Shell脚本read用法实现的文章就介绍到这了,更多相关Shell read内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-人工智能
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯