你的位置:首页 > 操作系统

[操作系统]Linux学习笔记 Shell编程之基础


1. 正则表达式

(1) 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令可以支持正则表达式;通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。

(2) 基础正则表达式

元字符作用
*前一个字符匹配0次或任意多次
.匹配除了换行符外任意一个字符
^匹配行首,如:^hello会匹配以hello开头的行
$匹配行尾,如:hello$会匹配以hello结尾的行
[]

匹配中括号中指定的任意一个字符,只匹配一个字符,如:[aoeiu]匹配任意一

个元音字符,[0-9]匹配任意一位数字,[a-z][0-9]匹配小写字母和一位数字构成的两位字符。

[^]匹配除中括号的字符以外的任意一个字符。
\ 转义符,用于将特殊符号的含义取消
\{n\}表示其前面的字符恰好出现n次。如:[0-9]\{4\}匹配4位数字,[1][3-8][0-9]\{9\}匹配手机号码 
\{n,\} 表示其前面的字符出现不小于n次,如:[0-9]\{2,\}表示两位及以上的数字
\{n,m\}表示其前面的字符至少出现n次,至多出现m次。如:[a-z]\{6,8\}匹配6到8位的小写字母。 

 例:创建一个文件file,其内容如下:

[root@localhost sh]# vim fileMr. Li said:he was a lucky dog!But since he met Hamster,he never saaaid those words.6666unbelievable!because,in faaaact,Hamster is the most lucky man!Later,Mr Li soid he would left.

#匹配所有内容,包括空白行grep "a*" file#匹配至少包含一个a的行grep "aa*" file#匹配至少包含两个连续a的字符串grep "aaa*" file#匹配至少包含四个连续a的字符串grep "aaaaa*" file

#"s..d"会匹配在s和d这两个字母间具有两个字符的单词grep "s..d" file#匹配在s和d字母之间的具有任意字符的单词grep "s.*d" file#匹配所有内容grep ".*" file

#匹配大写M开头的行grep "^M" file#匹配小写n结尾的行grep "n$" file#匹配空白行grep -n "^$" file

#匹配s和i之间要么是a,要么是o的行grep "s[ao]id" file#匹配任意一个数字grep "[0-9]" file#匹配小写字母开头的行grep "^[a-z]" file

#匹配不用小写字母开头的行grep "^[^a-z]" file#匹配不以字母开头的行grep "^[^a-zA-Z]" file

#匹配以"."结尾的行grep "\.$" file

#匹配a字母连续出现三次的字符串grep "a\{3\}" file#匹配包含连续三个数字的字符串grep "[0-9]\{3\}" file

#匹配至少用连续三个数字开头的行grep "^[0-9]\{3,\}[a-z]" file

#匹配在字母s和i之间至少有1个a,最多有3个a的行grep "sa\{1,3\}i" file

2. 字符截取命令

(1) cut字段提取命令

cut的格式为:cut [选项] 文件名

其中-f选项表示提取第几列,-d分隔符选项表示指定分隔符分割列。

例:有一个student.txt的文档,内容如下:

ID   Name  gender Mark1    LiNing M    862    HanMei F    903    Jim   M    83

① 提取单列:

[root@localhost sh]# cut -f 2 student.txt NameLiNingHanMeiJim

② 提取多列:

[root@localhost sh]# cut -f 2,4 student.txt Name  MarkLiNing 86HanMei 90Jim   83

③ 使用":"作为分隔符提取/etc/passwd中的第一列和第三列

[root@localhost sh]# cut -d ":" -f 1,3 /etc/passwdroot:0bin:1daemon:2adm:3lp:4

④ 提取/etc/passwd中多个用户的用户名的方法:

[root@localhost sh]# cat /etc/passwd | grep /bin/bash | grep -v root | cut -d ":" -f 1wsuser1user2user3

⑤ cut的局限

 查询根分区(/dev/sda5)的内存占用量时,cut命令即无法识别,识别仅限于制表符或由具体分隔符的符号,无法识别空格分隔的符号。

[root@localhost ~]# df -h | grep "sda5" | cut -f 5/dev/sda5    16G 1.8G  13G 13% /

(2) printf命令

printf的命令格式为:printf '输出类型输出格式' 输出内容

输出的类型包括:①%ns,表示输出字符串,n是数字指代输出几个字符;②%ni,输出整数,n指代输出几个数字;③%m.nf,输出浮点数,m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位数,其中2位是小数,6位是整数。

输出格式包括:

\a输出警告音
\b输出退格键
\f清空屏幕
\n换行
\r回车
\t水平输出退格键
\v垂直输出退格键

例:

[root@localhost sh]# printf %s 1 2 3 4 5 6123456[root@localhost sh]# printf %s %s %s 1 2 3 4 5 6%s%s123456#输出的数字每三个为一组,用单引号或双引号括起来输出格式[root@localhost sh]# printf '%s %s %s' 1 2 3 4 5 61 2 34 5 6#加入换行符[root@localhost sh]# printf '%s %s %s\n' 1 2 3 4 5 61 2 34 5 6#使用printf显示student.txt的内容(未调整格式)[root@localhost sh]# printf "%s" $(cat student.txt)IDNamegenderMark1LiNingM862HanMeiF903JimM83#更改student.txt的内容[root@localhost sh]# vim student.txt ID   Name  PHP   Linux  MySQL  gender Average1    LiNing 82   95   86   M    87.72    HanMei 72   98   86   F    85.33    Jim   99   83   93   M    91.7#使用printf显示更改后的stdudent.txt内容[root@localhost sh]# printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' $(cat student.txt)ID   Name  PHP   Linux  MySQL  gender Average1    LiNing 82   95   86   M    87.72    HanMei 72   98   86   F    85.33    Jim   99   83   93   M    91.7

 在awk命令的输出中支持print和printf命令,二者的区别在于print会在每个输出之后自动加入一个换行符(Linux默认没有print命令),printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需手工加入。

(3) awk命令

awk的功能比cut强大,可以识别空格符作为分隔符。其格式为:

awk '条件1{动作1} 条件2{动作2}...' 文件名

其中,一般将条件表达式作为条件,如x>10,x>=10,x<=10,动作包含格式化输出及流程控制语句。awk实际上是逐行处理文本内容的。

#使用awk读取student.txt中的第2,7行[root@localhost sh]# awk '{printf $2 "\t" $7 "\n"}' student.txt Name  AverageLiNing 87.7HanMei 85.3Jim   91.7#读取df -h的第1,5,6行内容[root@localhost sh]# df -h | awk '{printf $1 "\t" $5 "\t" $6 "\n"}'Filesystem   Use%  Mounted/dev/sda5    13%   /tmpfs  0%   /dev/shm/dev/sda1    12%   /boot/dev/sda2    4%   /home/dev/sdb1    4%   /root/disk1/dev/sdb5    3%   /root/disk5#结合使用awk和cut提取根分区(dev/sda5)的内存使用率[root@localhost sh]# df -h | grep /dev/sda5 | awk '{print $5}' | cut -d "%" -f 113

① BEGIN字段表示在所有的命令执行之前执行BEGIN后的命令,然后再处理随后的动作。

[root@localhost sh]# awk '{print $2 "\t" $7} BEGIN{print "This is a transcript"}' student.txt This is a transcriptName  AverageLiNing 87.7HanMei 85.3Jim   91.7

② FS内置变量用于指定分隔符,手工加入分隔符时,需强制将其设为BEGIN。

#打印出来的第一行数据未处理,因为先读入文本第一行,再进行处理的时候已略过第一行[root@localhost sh]# awk '{FS=":"}{print $1 "\t" $3}' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin   1daemon 2#因此,需要加上BEGIN字段执行[root@localhost sh]# awk '{print $1 "\t" $3} BEGIN{FS=":"}' /etc/passwdroot  0bin   1daemon 2

③ END字段表示其他命令执行完之后执行END后命令。

[root@localhost sh]# awk 'END{print "END!!"} {print $2 "\t" $7}' student.txt Name  AverageLiNing 87.7HanMei 85.3Jim  

④ 关系运算符

#提取平均成绩大于87的Name字段[root@localhost sh]# cat student.txt | grep -v Name | awk '$7>=87{print $2}'LiNingJim

(4) sed命令

sed是一种几乎包含所有UNIX平台(包括Linux)的轻量级编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。vi命令只能修改文本内容,sed命令既可以修改内容,可以修改命令的结果,shell编程中常用。其格式为:

sed [选项] '[动作]' 文件名

其中:一般sed命令会把所有数据都输出到屏幕,如果加入-n选项,则只会把经过sed命令处理的行输出到屏幕上;-e命令允许对输入数据应用多条sed命令编辑;-i选项表示用sed的修改结果直接修改读取数据的文件,而不是输出到屏幕。

sed中的动作包括:

a \追加,在当前行后追加一行或多行。添加多行时,出最后一行外,每行末尾需要用"\"代表数据未完结
c \行替换,用c后面的字符串替换原数据行,替换多行时,出最后一行外,每行末尾需用"\"代表数据未完结
i \插入,在当前行前插入一行或多行,插入多行时,除最后一行外,每行末尾需用"\"代表数据未完结
d删除指定行
p打印输出指定行
s字串替换,用一个字符串替换另外一个字符串。格式为"行范围s/旧字串/新字串/g"

 

例:

#输出student.txt的第二行[root@localhost sh]# sed '2p' student.txt ID   Name  PHP   Linux  MySQL  gender Average1    LiNing 82   95   86   M    87.71    LiNing 82   95   86   M    87.72    HanMei 72   98   86   F    85.33    Jim   99   83   93   M    91.7#加入-n选项[root@localhost sh]# sed -n '2p' student.txt 1    LiNing 82   95   86   M    87.7#删除第二行到第四行的数据,但不修改文件本身[root@localhost sh]# sed '2,4d' student.txt ID   Name  PHP   Linux  MySQL  gender Average#在第二行后追加hello[root@localhost sh]# sed '2a hello' student.txtID   Name  PHP   Linux  MySQL  gender Average1    LiNing 82   95   86   M    87.7hello2    HanMei 72   98   86   F    85.33    Jim   99   83   93   M    91.7#在第二行前插入两行数据[root@localhost sh]# sed '2i hello \> world' student.txtID   Name  PHP   Linux  MySQL  gender Averagehello world1    LiNing 82   95   86   M    87.72    HanMei 72   98   86   F    85.33    Jim   99   83   93   M    91.7#数据替换[root@localhost sh]# sed '2c No such person' student.txt ID   Name  PHP   Linux  MySQL  gender AverageNo such person2    HanMei 72   98   86   F    85.33    Jim   99   83   93   M    91.7#字串替换#将第三行的72换成100[root@localhost sh]# sed '3s/72/100/g' student.txt ID   Name  PHP   Linux  MySQL  gender Average1    LiNing 82   95   86   M    87.72    HanMei 100   98   86   F    85.33    Jim   99   83   93   M    91.7#同时把LiNing和Jim替换为空[root@localhost sh]# sed -e 's/LiNing//;s/Jim//g' student.txt ID   Name  PHP   Linux  MySQL  gender Average1        82   95   86   M    87.72    HanMei 100   98   86   F    85.33        99   83   93   M    91.7#加入-i选项Jim改为Tom直接写入文件[root@localhost sh]# sed -i '4s/Jim/Tom/g' student.txt [root@localhost sh]# cat student.txt ID   Name  PHP   Linux  MySQL  gender Average1    LiNing 82   95   86   M    87.72    HanMei 100   98   86   F    85.33    Tom   99   83   93   M    91.7

3. 字符处理命令

(1) sort排序命令

格式为:sort [选项] 文件名

其中-f选项表示忽略大小写;-n选项以数值型进行排序,默认使用字符串型排序;-r选项表示反向排序;-t选项表示指定分隔符,默认的分隔符为制表符;-k n[,m]选项表示按照指定的字段范围排序,从第n字段开始,m字段结束(默认到行尾)。

#排序用户信息文件[root@localhost sh]# sort /etc/passwdabrt:x:173:173::/etc/abrt:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinbin:x:1:1:bin:/bin:/sbin/nologin......#反向排序[root@localhost sh]# sort -r /etc/passwdws:x:500:500::/home/ws:/bin/bashvcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologinuucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin......#指定分隔符为":",且只使用第三字段排序(默认为zi)[root@localhost sh]# sort -t ":" -k 3,3 /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologinuucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologin......#对第三序列进行数值排序[root@localhost sh]# sort -n -t ":" -k 3,3 /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

 (2) 统计命令wc

格式为:wc [选项] 文件名

其中,-l选项表示只统计行数;-w选项表示只统计单词数;-m选项表示只统计字符数。

4. 条件判断式

(1) 按照文件类型进行判断

测试选项作用
-b 文件判断该文件是否存在,且是否为块设备文件
-c 文件判断该文件是否存在,且是否为字符设备文件
-d 文件判断该文件是否存在,并且是否为目录文件
-e 文件判断该文件是否存在
-f 文件判断该文件是否存在,且是否为普通文件
-L 文件判断该文件是否存在,且是否为符号链接文件
-p 文件判断该文件是否存在,且是否为管道符文件
-s 文件判断该文件是否存在,并且是否为空
-S 文件判断该文件是否存在,且是否为套接字文件

两种判断格式:

#①查看root下的install.log是否存在[root@localhost ~]# test -e /root/install.log#0表示存在[root@localhost ~]# echo $?0#②脚本当中常用的判断格式为中括号,同样执行上面的查询,注意中括号两端有空格[root@localhost ~]# [ -e /root/install.log ] && echo $?0#第一条命令执行正确,打印yes,否则打印no[root@localhost ~]# [ -d /tmp/ ] && echo "yes" || echo "no"yes

 

(2) 按照文件的权限进行判断

测试选项作用
-r 文件判断该文件是否存在,且是否拥有读权限
-w 文件判断该文件是否存在,且是否拥有写权限
-x 文件判断该文件是否存在,且是否拥有执行权限
-u 文件判断该文件是否存在,且是否拥有SUID权限
-s 文件判断该文件是否存在,且是否拥有SGID权限
-k 文件判断该文件是否存在,且是否拥有SBit权限
#只要u、g、o中有一个拥有写权限,即返回yes[root@localhost tmp]# [ -w sh/student.txt ] && echo yes || echo noyes

 

(3) 两个文件之间进行比较

测试选项作用
文件1 -nt 文件2判断文件1的修改时间是否比文件2的新
文件1 -ot 文件2判断文件1的修改时间是否比文件2的旧
文件1 -ef 文件2判断文件1和文件2的Inode号是否一致,可理解为两文件是否为同一个文件(判断硬链接的好方法)
[root@localhost sh]# pwd/tmp/sh#创建硬链接[root@localhost sh]# ln student.txt ../student1.txt#判断两文件是否为同一文件[root@localhost sh]# [ student.txt -ef ../student1.txt ] && echo yes || echo noyes

 

(4)两个整数之间的比较

测试选项作用
整数1 -eq 整数2判断整数1是否和整数2相等
整数1 -ne 整数2判断整数1是否和整数2不相等
整数1 -gt 整数2判断整数1是否大于整数2
整数1 -lt 整数2判断整数1是否小于整数2
整数1 -ge 整数2判断整数1是否大于等于整数2
整数1 -le 整数2判断整数1是否小于等于整数2
[root@localhost sh]# [ 23 -gt 22 ] && echo yes || echo noyes[root@localhost sh]# [ 23 -le 22 ] && echo yes || echo nono

 

(5) 字符串的判断

测试选项作用
-z 字符串判断字符串是否为空
-n 字符串判断字符串是否为非空
字串1==字串2判断字符串1是否和字符串2相等
字串1!=字串2判断字符串1是否和字符串2不相等
[root@localhost sh]# name=ws[root@localhost sh]# [ -z "$name" ] && echo yes || echo nono[root@localhost sh]# name1=ws[root@localhost sh]# [ "$name"=="$name1" ] && echo yes || echo noyes

 

(6) 多重条件判断

测试选项作用
判断1 -a 判断2逻辑与,判断1和判断2都成立,最终的结果才为真
判断1 -o 判断2逻辑或,判断1和判断2有一个成立,最终的结果即为真
! 判断逻辑非,使原始的判断式取反
#判断变量aa是否有值,并且其值是否大于23[root@localhost sh]# [ -n "$aa" -a "$aa" -gt 23 ] && echo yes || echo nono

 




新疆旅游地图线路大全新疆旅游多少钱新疆旅游攻略大全新疆旅游攻略自助游新疆旅游报价价格2015年五一假期中国旅游景点排行参考 2015年六一儿童节游戏大全 2015广西三月三放假规定 2015最新幼儿园儿童节主持词 2015清溪赏花节有什么花?清溪赏花旅游节要门票吗? 漫步厦门五大城市公园 最美的风景都是免费的 2015清溪赏花节活动介绍?清溪赏花旅游节有哪些好玩的? 畅游湖北鱼木寨一睹遗世的千年古寨风貌 爱琴海在哪里__爱琴海怎么去_爱琴海在哪个国家 比萨斜塔在哪儿_比萨斜塔在哪个国家_比萨斜塔交通_比萨斜塔门票 长白山天池在哪里_长白山天池怎么走_长白山天池在哪个省 马来西亚沙巴水上清真寺景点介绍_门票_交通 去泰国旅游能办落地签吗?价格多少? 世界旅游胜地有哪些? 春节去马尔代夫旅游好吗?大概要多少钱? 马尔代夫天气预报,马尔代夫11月份天气怎样? AT28HC256F-70JC Datasheet AT28HC256F-70JC Datasheet AT28HC256F-70JI Datasheet AT28HC256F-70JI Datasheet AT28HC256F70JI Datasheet AT28HC256F70JI Datasheet 长春跟团港澳四日游行程 长春跟团港澳四日游行程 长春跟团港澳四日游行程 从佳木斯跟团去港澳两日游 从佳木斯跟团去港澳两日游 从佳木斯跟团去港澳两日游 牡丹江去香港两日旅游 牡丹江去香港两日旅游 牡丹江去香港两日旅游