01 正则表达式入门
在Linux中,grep,sed,awk等文本工具都支持通过正则表达式进行模糊匹配。
# 匹配所有包含abc的行
cat /root/hello.txt | grep abc
# 匹配以ab开头的所有行
cat /root/hello.txt | grep ^ab
# 匹配以bc结尾的所有行
cat /root/hello.txt | grep bc$
# .可匹配任意一个字符
cat /root/hello.txt | grep r..t # 匹配所有包含rxxt的行 例如root rabt rxyt
# *匹配任意次的某字符
cat /root/hello.txt | grep ro*t # 匹配包含rt rot root rooot的所有行
# 匹配开头是a 结尾是bash的所有行
cat /root/hello.txt | grep ^a.*bash$ # 扩展:^a.*var.*bash$
[]
表示匹配某个范围内的一个字符
# 匹配6或8(包含6或8的行,下同)
cat /root/hello.txt | grep [6,8]
# 匹配一个数字
cat /root/hello.txt | grep [0-9]
# 匹配任意长度的数字字符串
cat /root/hello.txt | grep [0-9]*
# 匹配一个小写字母字符
cat /root/hello.txt | grep [a-z]
# 匹配任意长度的字母字符串
cat /root/hello.txt | grep [a-z]*
# 匹配一个a-c或e-f之间的任意字符串(a b c e f)
cat /root/hello.txt | grep [a-c,e-f]
# 会匹配rt rat rabt rbact rccbbat等所有行
cat /root/hello.txt | grep r[a,b,c]*t
使用\
匹配特殊字符
# 匹配包含$符号的行 注意需要使用单引号括起来
cat /root/hello.txt | grep '\$'
练习:匹配手机号
# 普通写法
echo "13456789001" | grep ^1[34578][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$
# 支持扩展表达式的写法 使用-E参数 {9}表示重复9次
echo "13456789001" | grep -E ^1[34578][0-9]{9}$
02 文本处理工具
2.1 cut工具
语法:
cut [参数] 文件名
-f
提取第几列
-d
指定分隔符 默认为\t
示例:
# 有如下内容的文件 空格分隔
a b c
d e f
good bad ok
# 获取第一列(指定以空格分隔) 输出 a d good(三行)
cut -d " " -f 1 cut.txt
# 获取第二三列
cut -d " " -f 2,3 cut.txt
# 获取系统PATH变量值中第2个":"开始后的所有路径
echo $PATH | cut -d ":" -f 3-
# 获取ip地址
ifconfig | grep netmask | cut -d " " -f 10
2.2 awk工具
awk是一个强大的文本分析工具,把文件逐行读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
语法:
awk [参数] '/pattern1/{action1} /pattern2/{action2} ...' 文件名
pattern
awk在数据中查找的内容(正则表达式)
action
找到匹配内容时执行的一系列命令
-F
指定输入文件分割符
-v
赋值一个用户定义变量
示例:
# 搜索passwd文件中以root关键字开头的所有行 并输出该行的第7列
cat /etc/passwd | awk -F ":" '/^root/{print $7}' # print是awk提供的 用于输出
# 搜索passwd文件中以root关键字开头的所有行 并输出该行的第1列和第7列 中间以,分隔
cat /etc/passwd | awk -F ":" '/^root/{print $1","$7}'
# 显示passwd第1列和第7列 以,分隔 且在首行前添加列名user shell 在尾行后添加end of file字样
cat /etc/passwd | awk -F ":" 'BEGIN{print "user shell"} {print $1","$7} END{print "end of file"}'
# 将passwd文件中的用户id增加数值1并输出
cat /etc/passwd | awk -F ":" '{print $3+1}'
# 将passwd文件中的用户id增加数值2并输出(使用变量)
cat /etc/passwd | awk -v n=2 -F ":" '{print $3+n}'
awk内置变量
FILENAME
文件名
NR
已读的记录数(行号)
NF
浏览记录的域的个数(切割后列的个数)
# 使用内置变量
awk -F ":" '{print "文件名:"FILENAME " 行号:"NR " 列数:"NF}' /etc/passwd
# 输出空行的行号
ifconfig | grep -n ^$ # -n表示输出显示行号
ifconfig | awk '/^$/{print NR}' # 方式二
# 输出IP地址
ifconfig | awk '/netmask/{print $2}'
03 综合运用 - 发送消息
- 需求
实现一个向某个用户快速发送消息的脚本,输入用户名作为第一个参数,后面直接跟要发送的消息。脚本需要检测用户是否登录在系统中、是否打开消息功能,以及当前发送消息是否为空。 - 提示
使用Linux自带的mesg和write工具,向同一系统的其他用户发送消息。
#!/bin/bash
# 查看用户是否登录 第1个$1是用户的输入 第1个$1是切分后的第1个值
login_user=$(who | grep -i -m 1 $1 | awk '{print $1}') # -i表示忽略大小写 -m 1表示筛选出来取第1行
if [ -z $login_user ] # -z表示判断是否为空
then
echo "$1 不在线"
echo "脚本退出..."
exit
fi
# 查看用户是否能接收消息
is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}') # -T参数可查看用户是否开启了消息接收功能
if [ $is_allowed != "+" ]
then
echo "$1 没有开启消息功能"
echo "脚本退出..."
exit
fi
# 确认是否有消息发送
if [ -z $2 ]
then
echo "消息为空 无法发送"
echo "脚本退出..."
exit
fi
# 从参数中获取要发送的消息
msg=$(echo $* | cut -d " " -f 2-) # 以空格分隔 取第2列及以后的所有参数视为要发送的消息
# 获取接收用户登录的终端
user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}')
# 写入要发送的消息
echo $msg | write $login_user $user_terminal
if [ $? -eq 0 ]
then
echo "发送成功"
else
echo "发送失败"
fi
exit