Shell编程之正则表达式与字符处理
编辑Shell编程之正则表达式与字符处理
正则表达式与通配符
正则表达式用来在文件中匹配符合条件的字符串
,正则是包含匹配
,grep,awk,sed等命令可以支持正则表达式
通配符用来匹配符合条件的文件名
,通配符是完全匹配
,ls |find| cp
这些命令不支持正则表达式,所以只能用shell自己的通配符进行匹配了
注意这个概念只适合Linux系统
通配符
-
*
匹配任意内容- 例如:
ls *
列出当前目录的所有文件,包括目录下的子文件
- 例如:
-
?
匹配一个内容ls misty?zhang
匹配以misty开头以zhang结尾中间可以是任意一个字符的一个字符串ls misty???
匹配以misty开头后面可以是任意三个字符的字符串
-
[]
匹配中括号中的一个字符ls misty[io]zhang
匹配一个以misty开头zhang结尾,中间可以是括号中匹配的一个字符的字符串
在绝大多数的语言当中没有通配符,只有正则表达式,通配符只是正则表达式的符号概念实际还是正则表达式,但是在系统当中通配符用来匹配文件名的
正则表达式
正则表达式是用于描述字符排列和匹配模式的一种语法规则,主要用于字符串的模式分割,匹配,查找以及替换操作
基础正则表达式
-
grep "a*" test.txt
匹配*前的a
字符0次到任意多次,所以文档中的内容会全部匹配输出,当然匹配的部分会标红(如果grep 设置了如本文下的别名)*
前面的一个字符是没有作用的代表匹配所有内容包括空白行"aa*"
匹配至少包含有一个a的行"aaa*"
匹配至少包含有两个连续个a的字符串
-
grep “aaaaa*” test.txt
匹配至少包含四个连续的a的字符串 -
.
匹配除了换行符之外的任意一个字符"s..d"
会匹配在s和d这两个字母之间一定有两个字符的字符串"s..d"
会匹配s和d字母之间有任意字符".*"
匹配所有内容
-
"^"
"$"
匹配行首和匹配行尾"^M
匹配以大写M开头的行"M$"
匹配以大写M结尾的行"^$"
匹配空白行,grep -n "^$" test.txt
匹配空白行的行号
-
[]
匹配括号中指定的任意一个字符,只匹配一个字符- "s[ao]id":匹配a或者o中的任意一个
- "[0-9]" 匹配任意一个数字
- “[a-z]” 匹配任意一个小写字母
注意
^
的语法:在[]外部代表行首匹配,在[]内部代表取反^[^a-z]
匹配不用小写开头的行,^[^a-zA-Z]
匹配不用字母开头的行
-
转义符
\
-
\.$
匹配使用 "." 结尾的行 ;如果不加转义符.$
代表匹配任何字符结尾的行(除了空行) -
\{n\}
表示其前面的字符恰好出现n次-
a\{3\}
匹配a字母连续出现三次的字符串 -
[0-9]\{3\}
匹配包含连续的三个数字的字符串 -
\{n,\}
匹配其前面的字符出现不小于n次 -
^[0-9]\{3,\}[a-z]
匹配最少用三个连续数字开头的行 -
\{n,m\}
匹配其前面的字符至少出现n次最多m次 -
sa\{1,3\}i
在字母a和字母i之间至少有一个a至多有3个a
-
-
正则表达式案例
-
[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}
匹配日期格式 YYYY-MM-DD -
[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\
匹配ip地址 -
仅适用于从文档中间匹配正则,但是不适用于将ip写入文档
?和()是扩展正则;表达式语法和Java有点区别
扩展正则表达式
[省略]
字符截取命令
cut字段提取命令
cut [选项] 文件名
-
-f
列号:提取第几列 -
-d
分隔符:按照指定分隔符分割列(默认分割符号是制表符tab) -
实例:
grep "/bin/bash" /etc/passwd |grep -v "root" |cut -f 1 -d ":"
获取用户排除root用户截取第一列的值就是普通用户- 实例:
grep "/bin/bash" /etc/passwd |grep -v "root" |cut -f 1,3 -d ":"
获取用户排除root用户截取第一列和第三列的值就是普通用户用户名和uid
- 实例:
管道符操作不需要后接文件名,操作的结果是前一条命令传递的返回值;若是没有分隔符(当做分隔符在最后)则这一整行作为单元列
cut命令的局限
df -h |cut -d " " -f 1,3
若是使用空格作为分隔符,处理起来会有问题,多个空格连在一起无法处理
df 命令用于查看分区的使用状况
printf命令-格式化输出命令
echo是原格式输出;printf不支持数据流操作也就不支持管道符;print的输出内容需要引号括起来
语法:printf '输出类型输出格式' 输出内容
输出类型
%ns
:输出字符串,n是数字指代输出几个字符%ni
:输出整数,n是数字指代输出几个数字%m.nf
:输出浮点数,m,n都是数字,指代输出的整数位数和小数位数,如%8.2f代表共输出8位数,其中两位是小数,六位是整数
输出格式
\a
:输出警告声音\b
:输出退格键也就是backpace键\f
:清除屏幕\n
:换行\r
:回车,也就是enter键\t
:水平输出退格键,也就是tab键\v
:垂直输出退格键,也就是tab键
操作实例
id name gender mark
1 sange F 60
2 lisi F 70
3 wangsu F 80
printf $(cat student.txt) #这样输出有问题
printf '%s' $(cat student.txt) #不调整格式输出,这样输出没有任何格式,内容挤压在一起
printf '%s\t%s\t%s\t%s\n' $(cat student.txt) #格式化输出,每隔四个换一行
`</pre>
在awk命令的输出中支持print和printf命令
-
print:print会在给个输出之后自动加入一个换行符(linux默认没有print命令)
-
printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
awk命令
语法:
awk '条件1{动作1}条件2{动作2}...' 文件名
,有条件按照条件执行动作,没有条件直接执行动作 -
条件(pattern)
- 一般使用关系表达式作为条件
x>10
判断变量 x是否大于10x>=10
大于等于x<=10
小于等于
-
动作(action)
- 格式化输出
- 流程控制语句
操作实例
# 按行读出文档中的数据,再按条件截取(本例没有条件)第二个和第四个字段
awk '{print[f] $2 "-t" $4 "\n" }' student.txt #没有条件直接执行动作,因为这里已经有单引号所以转义符用双引号,并且不可以省略
# 仅仅截取根分区的磁盘占用情况,获取第五个参数,再去除%即可的到分区占用的比例
df -h | grep "/dev/sda5" | awk `{print $5 } | cut -d "%" -f 1`
# BEGIN 和 END
# 在所有的动作开始之前 执行一段输出BEGIN代表动作开始之前对应ENG(如果动作结束)
awk 'BEGIN{printf "this is a transcript \n"}{printf $2 "\t" $4 "\n"}' student.txt
## FS内置变量
#打印普通用户的第一列和第三列数据分隔符是`:`,导致第一行没有正确输出;
# 因为awk是先读取一行然后赋予变量之后再执行动作,所以分隔符没有来得及指定
cat /etc/passwd |grep /bin/bash |awk '{FS=":"}{print $1 "\t" $3}'
# 用BEGIN解决这个问题,在所有的动作执行之前,执行指定分隔符而不是默认的分隔符
cat /etc/passwd |grep /bin/bash |awk 'BEGIN{FS=":"}{print $1 "\t" $3}'
# 关系运算符
# 读取文本学生表排除表头,取出成绩大于70的学生打印出姓名,注意条件卸载大括号之外
cat student.txt |grep -v Name |awk '$4>=70{print $2 "\n"}'
```
#### sed命令-字符替换命令
sed 是一种几乎包括所有Unix平台(包括Unix)的轻量级流编辑器,sed主要用来将数据进行选取,替换,删除,新增的命令
* `sed [选项] '[动作]' 文件名`
* 选项
* `-n`:一般sed命令会把所有数据都输出到屏幕上,如果加入此选项只会吧经过处理的行输出到屏幕上
* `-e`:允许对输入数据应用多条sed命令编辑
* `-i`:用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出
* 动作
* `-a`: 追加,在当前行后添加一行或者多行
* `-c`: 行替换,用c后面的字符串替换原数据行* `-i`: 插入,在当前行前插入一行或者多行,
* `-d`: 删除,删除指定行* `-p`: 打印输出指定的行* `-s`: 字符替换,用一个字符串替换林一个字符串 ,格式为"行范围s/旧字串/新字串/g"(和vim的替换格式类似)
**操作实例**
```shell
#查看文件的第二行,但是会把文本内容全部列出
sed '2p' student.txt
#查看文件的第二行,并且输出到屏幕
sed -n '2p' student.txt
# 在第二行后追加一段文本 append
sed '2a this is the text of test ' student.txt
# 在第二行前插入一行数据 insert
sed '2i this is the text of test ' student.txt
# 整行替换:将第二行替换成另一个字符串
sed '2c this is the text of test' student.txt
#字符串部分替换
sed 's/旧字串/新字串/g' 文件名
#在第三行中将60换成99
sed '3s/60/99/g' student.txt
#在第三行中将60换成99,并且sed操作的数据直接写入文件
sed -i '3s/60/99/g' student.txt
# 同时把指定字符串替换成空,-e允许多条同时编辑
sed -e 's/this is test1//g;s/this is test1//g' student.txt;
> 和vi有很多相似的地方,区别在于vim是给用户直接使用的,sed是为脚本或者程序提供文本处理支持
### 字符处理命令
sort命令-排序命令
-
sort [选项] 文件名
-
选项:
-f
: 忽略大小写-n
: 以数值型进行排序,默认使用字符串型进行排序-r
: 反向排序-t
: 指定分隔符,默认分隔符是制表符-k [n,m]
: 按照指定的字段范围进行排序,从第n字段开始,m字段结束(默认到行尾)
操作实例
sort /etc/passwd # 排序用户信息文件,按照字母顺序
sort -r /etc/passwd # 反向排序
# 指定分隔符是":" ,用第三字段开头,第三字段结尾排序,就是只用第三字段排序
sort -t ":" -k 3,3 # 会有个问题,会有数值小的在下面,是因为默认是字符串排序的
# 指定分隔符是":" ,作为数值类型排序 ,用第三字段开头,第三字段结尾排序,就是只用第三字段排序
sort -n -t ":" -k 3,3
wc命令-统计命令
-
wc [选项] 文件名
-
选项
-l
:只统计行数-w
:只统计单词数,单词使用空格分割的-m
:只统计字符数
# 大致统计用户数 wc -l /etc/passwd
### 其他相关命令和配置
别名配置 `~/.bashrc`
```shell
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi='vim'
alias grep='grep --color=auto'
使配置文件生效source~/.basjrc
- 0
- 0
-
分享