打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
shell 利用read与键盘进行交互, 来取得变量的值_布萨空间
userphoto

2009.04.07

关注
使用read来进行变量分配
1 #!/bin/bash                        2 # "Reading" 变量.                        3                        4 echo -n "Enter the value of variable 'var1': "                        5 # -n 选项, 阻止换行.                        6                        7 read var1                        8 # 注意: 在var1前面没有'$', 因为变量正在被设置.                        9                        10 echo "var1 = $var1"                        11                        12                        13 echo                        14                        15 # 一个单独的'read'语句可以设置多个变量.                        16 echo -n "Enter the values of variables 'var2' and 'var3' (separated by a space or tab): "                        17 read var2 var3                        18 echo "var2 = $var2      var3 = $var3"                        19 # 如果你只输入了一个值, 那么其他的变量还是处于未设置状态(null).                        20                        21 exit 0

一个不带变量参数的read命令, 将会把来自键盘的输入存入到专用变量$REPLY中.


例子 11-4. 当使用一个不带变量参数的read命令时, 将会发生什么?

1 #!/bin/bash                        2 # read-novar.sh                        3                        4 echo                        5                        6 # -------------------------- #                        7 echo -n "Enter a value: "                        8 read var                        9 echo "\"var\" = "$var""                        10 # 到这里为止, 都与期望的一样.                        11 # -------------------------- #                        12                        13 echo                        14                        15 # ------------------------------------------------------------------- #                        16 echo -n "Enter another value: "                        17 read           #  没有变量分配给'read'命令, 所以...                        18                #+ 输入将分配给默认变量, $REPLY.                        19 var="$REPLY"                        20 echo "\"var\" = "$var""                        21 # 这部分代码和上边的代码等价.                        22 # ------------------------------------------------------------------- #                        23                        24 echo                        25                        26 exit 0

一般的, 当输入给read时, 输入一个\, 然后回车, 将会阻止产生一个新行. -r选项将会让 \ 转义.


例子 11-5. read命令的多行输入

1 #!/bin/bash                        2                        3 echo                        4                        5 echo "Enter a string terminated by a \\, then press <ENTER>."                        6 echo "Then, enter a second string, and again press <ENTER>."                        7 read var1     # 当 read $var1 时, "\" 将会阻止产生新行.                        8               #     first line                         9               #     second line                        10                        11 echo "var1 = $var1"                        12 #     var1 = first line second line                        13                        14 #  对于每个以 "\" 结尾的行,                        15 #+ 你都会看到一个下一行的提示符, 让你继续向var1输入内容.                        16                        17 echo; echo                        18                        19 echo "Enter another string terminated by a \\ , then press <ENTER>."                        20 read -r var2  # -r 选项会让 "\" 转义.                        21               #     first line                         22                        23 echo "var2 = $var2"                        24 #     var2 = first line                         25                        26 # 第一个 <ENTER> 就会结束var2变量的录入.                        27                        28 echo                        29                        30 exit 0

read命令有些有趣的选项, 这些选项允许打印出一个提示符, 然后在不输入ENTER的情况下, 可以读入你所按下的字符的内容.

1 # 不敲回车, 读取一个按键字符.                        2                        3 read -s -n1 -p "Hit a key " keypress                        4 echo; echo "Keypress was "\"$keypress\""."                        5                        6 # -s 选项意味着不打印输入.                        7 # -n N 选项意味着只接受N个字符的输入.                        8 # -p 选项意味着在读取输入之前打印出后边的提示符.                        9                        10 # 使用这些选项是有技巧的, 因为你需要用正确的顺序来使用它们.                        11 

read命令的-n选项也可以检测方向键, 和一些控制按键.


例子 11-6. 检测方向键

1 #!/bin/bash                        2 # arrow-detect.sh: 检测方向键, 和一些非打印字符的按键.                        3 # 感谢, Sandro Magi, 告诉了我们怎么做到这点.                        4                        5 # --------------------------------------------                        6 # 按键所产生的字符编码.                        7 arrowup='\[A'                        8 arrowdown='\[B'                        9 arrowrt='\[C'                        10 arrowleft='\[D'                        11 insert='\[2'                        12 delete='\[3'                        13 # --------------------------------------------                        14                        15 SUCCESS=0                        16 OTHER=65                        17                        18 echo -n "Press a key...  "                        19 # 如果不是上边列表所列出的按键, 可能还是需要按回车. (译者注: 因为一般按键是一个字符)                        20 read -n3 key                      # 读取3个字符.                        21                        22 echo -n "$key" | grep "$arrowup"  # 检查输入字符是否匹配.                        23 if [ "$?" -eq $SUCCESS ]                        24 then                        25   echo "Up-arrow key pressed."                        26   exit $SUCCESS                        27 fi                        28                        29 echo -n "$key" | grep "$arrowdown"                        30 if [ "$?" -eq $SUCCESS ]                        31 then                        32   echo "Down-arrow key pressed."                        33   exit $SUCCESS                        34 fi                        35                        36 echo -n "$key" | grep "$arrowrt"                        37 if [ "$?" -eq $SUCCESS ]                        38 then                        39   echo "Right-arrow key pressed."                        40   exit $SUCCESS                        41 fi                        42                        43 echo -n "$key" | grep "$arrowleft"                        44 if [ "$?" -eq $SUCCESS ]                        45 then                        46   echo "Left-arrow key pressed."                        47   exit $SUCCESS                        48 fi                        49                        50 echo -n "$key" | grep "$insert"                        51 if [ "$?" -eq $SUCCESS ]                        52 then                        53   echo "\"Insert\" key pressed."                        54   exit $SUCCESS                        55 fi                        56                        57 echo -n "$key" | grep "$delete"                        58 if [ "$?" -eq $SUCCESS ]                        59 then                        60   echo "\"Delete\" key pressed."                        61   exit $SUCCESS                        62 fi                        63                        64                        65 echo " Some other key pressed."                        66                        67 exit $OTHER                        68                        69 #  练习:                        70 #  -----                        71 #  1) 使用'case'结构来代替'if'结构,                        72 #+    这样可以简化这个脚本.                        73 #  2) 添加 "Home", "End", "PgUp", 和 "PgDn" 这些按键的检查.

 

对于read命令来说, -n选项不会检测ENTER(新行)键.

read命令的-t选项允许时间输入(参考例子 9-4).

read命令也可以从重定向的文件中"读取"变量的值. 如果文件中的内容超过一行, 那么只有第一行被分配到这个变量中. 如果read命令的参数个数超过一个, 那么每个变量都会从文件中取得一个分配的字符串作为变量的值, 这些字符串都是以定义的空白字符来进行分隔的. 小心使用!


例子 11-7. 通过文件重定向来使用read命令

1 #!/bin/bash                        2                        3 read var1 <data-file                        4 echo "var1 = $var1"                        5 # var1将会把"data-file"的第一行的全部内容都为它的值.                        6                        7 read var2 var3 <data-file                        8 echo "var2 = $var2   var3 = $var3"                        9 # 注意, 这里的"read"命令将会产生一种不直观的行为.                        10 # 1) 重新从文件的开头开始读入变量.                        11 # 2) 每个变量都设置成了以空白分割的字符串.                        12 #    而不是之前的以整行的内容作为变量的值.                        13 # 3) 而最后一个变量将会取得第一行剩余的全部部分(译者注: 不管是否以空白分割).                        14 # 4) 如果需要赋值的变量个数比文件中第一行以空白分割的字符串个数还多的话,                        15 #    那么这些变量将会被赋空值.                        16                        17 echo "------------------------------------------------"                        18                        19 # 如何用循环来解决上边所提到的问题:                        20 while read line                        21 do                        22   echo "$line"                        23 done <data-file                        24 # 感谢, Heiner Steven 指出了这点.                        25                        26 echo "------------------------------------------------"                        27                        28 # 使用$IFS(内部域分隔变量)来将每行的输入单独的放到"read"中,                        29 # 前提是如果你不想使用默认空白的话.                        30                        31 echo "List of all users:"                        32 OIFS=$IFS; IFS=:       # /etc/passwd 使用 ":" 作为域分隔符.                        33 while read name passwd uid gid fullname ignore                        34 do                        35   echo "$name ($fullname)"                        36 done </etc/passwd   # I/O 重定向.                        37 IFS=$OIFS              # 恢复原始的$IFS.                        38 # 这段代码也是Heiner Steven编写的.                        39                        40                        41                        42 #  在循环内部设置$IFS变量,                        43 #+ 而不用把原始的$IFS                        44 #+ 保存到临时变量中.                        45 #  感谢, Dim Segebart, 指出了这点.                        46 echo "------------------------------------------------"                        47 echo "List of all users:"                        48                        49 while IFS=: read name passwd uid gid fullname ignore                        50 do                        51   echo "$name ($fullname)"                        52 done </etc/passwd   # I/O 重定向.                        53                        54 echo                        55 echo "\$IFS still $IFS"                        56                        57 exit 0

 

管道输出到read命令中, 使用管道echo输出来设置变量将会失败.

然而, 使用管道cat输出看起来能够正常运行.

1 cat file1 file2 |                                    2 while read line                                    3 do                                    4 echo $line                                    5 done

但是, 就像Bj鰊 Eriksson所指出的:


例子 11-8. 管道输出到read中的问题

1 #!/bin/sh                                    2 # readpipe.sh                                    3 # 这个例子是由Bjon Eriksson所编写的.                                    4                                    5 last="(null)"                                    6 cat $0 |                                    7 while read line                                    8 do                                    9     echo "{$line}"                                    10     last=$line                                    11 done                                    12 printf "\nAll done, last:$last\n"                                    13                                    14 exit 0  # 代码结束.                                    15         # 下边是脚本的(部分)输出.                                    16         # 'echo'出了多余的大括号.                                    17                                    18 #############################################                                    19                                    20 ./readpipe.sh                                    21                                    22 {#!/bin/sh}                                    23 {last="(null)"}                                    24 {cat $0 |}                                    25 {while read line}                                    26 {do}                                    27 {echo "{$line}"}                                    28 {last=$line}                                    29 {done}                                    30 {printf "nAll done, last:$lastn"}                                    31                                    32                                    33 All done, last:(null)                                    34                                    35 变量(last)被设置在子shell中, 并没有被设置在外边.

在许多Linux发行版上, gendiff脚本通常都在/usr/bin下, 将find的输出通过管道传到while read结构中.

1 find $1 \( -name "*$2" -o -name ".*$2" \) -print |                                    2 while read f; do                                    3 . . .

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
linux read 用法
read命令
linux shell中的单引号与双引号的区别(看完就不会有引号的疑问了)
SHELL十三问之四:双引号与单引号差别在哪
Linux Bash Shell快速入门
Shell脚本
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服