Bash:选择结构之case
case与if
if用于选择的条件,不是很多的情况,如果选择的条件太多,一系列的if,elif,,也是醉了。没错,case在bash中的地位,和switch在C中的地位一样。但是用法可大有不同。
代码块
任何语言都有代码块的概念,C语言中的花括号{ },python中的冒号和缩进。bash中的代码块风格不是很统一。但是在选择结构中是相同的——反语。if结构使用if...fi标识一个代码块的作用域,而case也是用case...esac表示块作用域的。。
基本结构
看例子echo.sh:
#!/bin/bash
str="is good "
read -p "你喜欢什么颜色:" color
case $color in
red) echo -e "e[1;31m$color $str e[0m";;
green) echo -e "e[1;32m$color $str e[0m";;
yellow) echo -e "e[1;33m$color $str e[0m";;
blue) echo -e "e[1;34m$color $str e[0m";;
*) echo -e "e[1;30m这是什么颜色?e[0m";;
esac
这段代码,就是根据你的输入来显示不同颜色的文本。关于echo语句的写法,这里不细说,每句分别设置了不同的文本颜色。重点去看一下这个结构。
把变量color的值,依次和下面右括号里的值做比较,如果相同,就执行后面的语句。
来运行一下
两个分号;;
注意每个条件末尾都是两个分号。这很好理解,就像C语言的switch里面每个case都经常会有一个break一样。因为每个条件满足的时候,需要执行的语句可能不止一句。而在bash中多个语句在一行是用一个分号间隔的。这样两个分号就表示着语句结束,另外加一个空语句,也就是说要执行的语句都完成了。
与c语言的switch不同的是,c语言中每个条件(case语句)后面不一定都要有break,如果没有break,则继续执行下面的条件的语句。如果你想像c语言那样多个条件共用一套语句,怎么办呢?请继续阅读。
分号扭号;&
所谓扭号,就是And符号——&,我觉得叫扭号更简洁。。看一段C代码:
#include<stdio.h>
int main(){
char ans;
printf("你喜欢编程么:");
scanf("%c",&ans);
switch(ans){
case 'y':
case 'Y':printf("我也是n");break;
case 'n':
case 'N':printf("sorry,跟你没什么好谈的n");break;
}
}
也就是说,在C中,case后面如果不加break,那么在执行完匹配的语句后,将接着执行,而不管下面的条件匹配不匹配,直到遇到break为止。这样的语法,十分灵活,那么bash中又如何实现呢?难道在末尾加一个分号?错错错。答案是一个分号加一个扭号。
#!/bin/bash
read -p "你喜欢编程么:(y/n):" ans
case $ans in
y);&
Y) echo "我也是";;
n);&
N) echo "sorry,跟你没什么好谈的";;
esac
分号分号扭号;;&
除了 ;&结束语句以外,还有一种是 ;;& 来结束语句的用法。但是意义有所不同,;;&的用法是使得条件越来越精确。
#!/bin/bash
read -p "请输入一个区号:" num
case $num in
*)echo -n "中国";;&
03*)echo -n "河北省";;&
??10)echo "邯郸市";;
??11)echo "石家庄";;
??17)echo "沧州市";;
07*)echo -n "江西省";;&
??91)echo "南昌市";;
??92)echo "九江市";;
??97)echo "赣州市";;
esac
关于通配符*和?,我们下面会讲到。这里,你只需要知道,条件语句以 ;;& 结束的时候,程序执行到这里不会停止,会继续测试下面条件,如果满足继续执行,直到遇到 ;; 或esac
注意,以上这两种扭号的用法,是bash自己的 特性,对于其他shell,并不支持。如果考虑移植性,就不要这样写了。仅仅用正规的两个分号就可以了。
右括号中的模式
基本正则
)右括号,类似c语言中switch中的case。然而与之不同的是,Bash中的右括号里面,不仅支持完整的字符串(c语言中只支持整型数据,包括int和char
,不支持字符串)还支持“模式”匹配。模式的概念,如果了解正则表达式,那么就很容易理解了。不过case语句中与正则表达式略有不同。貌似支持的并不完整。
- *是匹配0个或多个任何字符。
- ?是匹配一个字符。可以看做一个占位符。
- [ ]表示一个范围。
- ( )枚举字符串。但是需要转义
#!/bin/bash
read -p "请输入一个数字:" num
case $num in
2*)echo "匹配2*";;&
2?)echo "匹配2?";;&
[0-9])echo "匹配[0-9]";;
esac
方括号表示范围,你可以使用[123]来匹配1或2或3,而不是123。也可以使用[0-9]、[a-zA-Z]这样的写法,熟悉正则的同学,这些都不是问题。
注意我上面用到了 ;;& 也就是说在匹配了一个模式之后,不会停止,还会继续向下执行。执行效果:
枚举字符串
一般的写法比如(123|456|789)匹配123,456,789这三个数。但是因为case中右括号有特殊含义,所以进行了转义。
然后我的写法就是(123|456|789),但是这样有个问题就是789无法得到匹配,123和456倒是可以,我也是不明所以(见笑,知情者望告知)。
于是我又改了一版,终于匹配完全——(123|456|789|)。
现在加上一句到刚才的脚本中——(123|456|789 ))echo "匹配(123|456|789|)";;&
POSIX字符类
一般的编程语言中的正则表达式,支持w,d这类的字符类(Character Classes)。而Unix-like系统上,支持的字符类是POSIX风格的。
见下表
类 |
描 述 |
扩 展 |
---|---|---|
[:alnum:] |
字母和数字字符 |
[0-9a-zA-Z] |
[:alpha:] |
(letters)字母字符(字母) |
[a-zA-Z] |
[:ascii:] |
7位ASCII |
[x01-x7F] |
[:blank:] |
水平空白符(空格、制表符) |
[ t] |
[:cntrl:] |
控制字符 |
[x01-x1F] |
[:digit:] |
数字 |
[0-9] |
[:graph:] |
用墨水打印的字符(非空格、非控制字符) |
[^x01-x20] |
[:lower:] |
小写字母 |
[a-z] |
[:print:] |
可打印字符(图形类加空格和制表符) |
[tx20-xFF] |
[:punct:] |
任意标点符号,如句点(.)和分号(;) |
[-!"#$%&'( )*+,./:;<=>?@[\]^_'{|}~] |
[:space:] |
空白(换行、回车、制表符、空格、垂直制表符) |
[nrt x0B] |
[:upper:] |
大写字母 |
[A-Z] |
[:xdigit:] |
十六进制数字 |
[0-9a-fA-F] |
这个表是从网友那里复制的,原文《POSIX风格正则表达式》
实际使用的时候,还要在这些字符类的方括号外面,再套一层方括号才行。
#!/bin/bash
read -p "请任意输入,可以包含空格等空白符" ch
#echo $ch
case $ch in
*[[:lower:]]*)echo lower;;&
*[[:upper:]]*)echo upper;;&
*[[:digit:]]*)echo digit;;&
*[[:punct:]]*)echo punct;;&
*[[:ascii:]]*)echo ascii;;&
*[[:cntrl:]]*)echo cntrl;;&
*[[:print:]]*)echo print;;&
*[[:space:]]*)echo space;;&
*[[:xdigit:]]*)echo xdigit;;&
*[[:graph:]]*)echo graph;;&
*[[:blank:]]*)echo blank;;&
*[[:alnum:]]*)echo alnum;;&
*[[:alpha:]]*)echo alpha;;&
esac
这个脚本,大家自己去测试吧。当然了有些字符(比如控制字符)貌似不好输入。这样不好测试[:cntrl:]这个字符类,这里我告诉您一下,ascii码中27对应的控制字符就是ESC。测试脚本的时候,可以按一下ESC键。或者键入^[字符,也是一样的。
- 11g Active DataGuard初探(r5笔记第54天)
- Github 项目推荐 | 用于构建端对端对话系统和训练聊天机器人的开源库 —— DeepPavlov
- 我身边的一些数据库事故 (r5笔记第52天)
- 一个清理脚本的改进思路(r5笔记第51天)
- 【专业技术】Python爬虫:抓取手机APP的传输数据
- 海量数据迁移之传输表空间(一) (r5笔记第71天)
- 一条sql语句的改进探索(r5笔记第70天)
- 【专业技术】Node.js 究竟是什么?
- Github 项目推荐 | 用 Pytorch 实现的 WaveNet-Vocoder
- 重启数据库的一场闹剧(r5笔记第68天)
- 【C语言系列】基础语法案例分析(初级篇)
- 一次ORA-00600问题的排查和分析(r5笔记第64、65天)
- SpringMVC入门就这么简单
- pl/sql中的forall简单测试(r5笔记第63天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用SimpleITK读取和保存NIfTI/DICOM文件实例
- php中上传文件的的解决方案
- python 实现两个npy档案合并
- PHP使用函数用法详解
- 读取nii或nii.gz文件中的信息即输出图像操作
- PHP实现SMTP邮件的发送实例
- 多个Laravel项目如何共用migrations详解
- PHP实现文字写入图片功能
- php中file_get_contents()函数用法实例
- PHP通过GD库实现验证码功能示例
- Thinkphp 5.0实现微信企业付款到零钱
- 使用npy转image图像并保存的实例
- php实现有序数组旋转后寻找最小值方法
- 基于python实现音乐播放器代码实例
- PHP实现微信对账单处理