Shell编程之正则表达式与字符处理

正则表达式与通配符

正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配,grep,awk,sed等命令可以支持正则表达式

通配符用来匹配符合条件的文件名,通配符是完全匹配,ls |find| cp这些命令不支持正则表达式,所以只能用shell自己的通配符进行匹配了

注意这个概念只适合Linux系统

通配符
* * 匹配任意内容
* 例如:ls * 列出当前目录的所有文件,包括目录下的子文件
* ? 匹配一个内容
* ls misty?zhang 匹配以misty开头以zhang结尾中间可以是任意一个字符的一个字符串
* ls misty??? 匹配以misty开头后面可以是任意三个字符的字符串
* [] 匹配中括号中的一个字符
* ls misty[io]zhang 匹配一个以misty开头zhang结尾,中间可以是括号中匹配的一个字符的字符串

在绝大多数的语言当中没有通配符,只有正则表达式,通配符只是正则表达式的符号概念实际还是正则表达式,但是在系统当中通配符用来匹配文件名的

正则表达式

正则表达式是用于描述字符排列和匹配模式的一种语法规则,主要用于字符串的模式分割,匹配,查找以及替换操作

基础正则表达式

img

  • grep "a*" test.txt 匹配*前的字符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) #格式化输出,每隔四个换一行

在awk命令的输出中支持print和printf命令

  • print:print会在给个输出之后自动加入一个换行符(linux默认没有print命令)
  • printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
awk命令

语法:
awk '条件1{动作1}条件2{动作2}...' 文件名,有条件按照条件执行动作,没有条件直接执行动作

  • 条件(pattern)
    • 一般使用关系表达式作为条件
    • x>10判断变量 x是否大于10
    • x>=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的替换格式类似)

操作实例

#查看文件的第二行,但是会把文本内容全部列出
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

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi='vim'
alias grep='grep --color=auto'

使配置文件生效source~/.basjrc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值