正则表达式与常用文本处理工具

正则表达式与常用文本处理工具

  • 正则表达式概述
    • 基础正则表达式
      • 基础正则表达式元字符
    • 扩展正则表达式
      • 概述
      • 扩展元字符
  • 文本处理器
    • grep
      • 示例
    • sed
      • sed 命令
      • 示例
        • 输出文件内容
        • 删除符合条件的文本
        • 替换符合条件的文本
        • 迁移符合条件的文本
    • egrep
    • awk
      • 概述
      • 格式
      • 示例
        • 按行输出文本
        • 按字段输出文本
        • 通过管道、双引号调用 Shell 命令

正则表达式概述

正则表达式又称正规表达式、常规表达式。在代码中常简写为 regex、regexp 或 RE。正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,简单来说, 是一种匹配字符串的方法,通过一些特殊符号,实现快速查找、删除、替换某个特定字符串。
正则表达式对于系统管理员来说是非常重要的,系统运行过程中会产生大量的信息,这些信息有些是非常重要的,有些则仅是告知的信息。身为系统管理员如果直接看这么多的信息数据,无法快速定位到重要的信息,如“用户账号登录失败”“服务启动失败”等信息。这时可以通过正则表达式快速提取“有问题”的信息。
正则表达式的字符串表达方法根据不同的严谨程度与功能分为基本正则表达式与扩展正则表达式。基础正则表达式是常用正则表达式最基础的部分。在Linux系统中常见的文件处理工具中grep 与sed 支持基础正则表达式,而egrep 与awk 支持扩展正则表达式。

基础正则表达式

基础正则表达式是常用的正则表达式部分。

基础正则表达式元字符

^ :匹配输入字符串的开始位置。除非在方括号表达式中使用,代表不包含该字符集合。要匹配“^”字符本身,请使用“\”

$ :匹配输入字符串的结尾位置。如果设置了RegExp(正则表达式)对象的Multiline(多个)属性,则“$”也匹配‘\n’或‘\r’(换行)。
要匹配"$"字符本身,请使用“\$”

.:匹配除了“\n\r”之外的任何单个的字符

\:反斜杠,又叫转义字符,去除其紧跟的元字符或通配符的特殊意义。

*:匹配前面的子表达式零次或多次。要匹配“*”字符,请使用“\*”

[]:字符集合。匹配所包含的任意一个字符。例如,“[abc” 可以匹配“plain” 中的“a”

[^ ]:赋值字符集合。匹配未包含的一个任意字符。例如,“[^abc]”可以匹配“plain”中任何一个字母

[n1-n2]: 字符范围。匹配指定范围内的任意一个字符。例如,“[a-z]” 可以匹配“a”到“z”范围内的任意一个小写字母字符。

注意:只有连字符(-)在字符组内部,并且出现在两个字符之间时,才能表示子符的范围;如果出现在字符组的开头,则只能表示连字符本身

{n}: n是一个非负整数,匹配确定的n次。例如,“o{2}"不能匹配“Bob” 中的“o”,但是能匹配“food”中的“oo”

{n,}: n是一个非负整数,至少匹配n次。例如,“o{2,}”不能匹配“Bob” 中的“o”,但能匹配“fooood”中的所有o。

“o{1,}”等价于“o+”(至少出现1次)。“o{0,}”则等价于“o*"(至少出现0次)

{n,m}: m和n均为非负整数,其中n<=m, 最少匹配n次且最多匹配m次

扩展正则表达式

概述

通常情况下会使用基础正则表达式就已经足够了,但有时为了简化整个指令,需要使用范围更广的扩展正则表达式。使用扩展正则表达式,需要使用 egrep 或 awk 命令。

扩展元字符

+:匹配前面子表达式1次以上
例如:go+d,将匹配至少一个o(如god,good,goood...)

?:匹配前面子表达式0次或者1次
例如:go?d,将匹配gd或god

():括号中的字符串作为一个整体
例如:(xyz)+,将匹配xyz整体1次以上,如xyzxyz

|:以或的方式匹配字条串
例如1:good|food,将匹配good或者food
例如2:g(oo|la)d,将匹配good或者glad
(g|f)ood  good或者food

文本处理器

在Linux/UNIX 系统中包含很多种类的文本处理器或文本编辑器,其中包括我们之前学习过的VIM 编辑器与grep 等。而 grep,sed,awk 更是Shell 编程中经常用到的文本处理工具, 被称之为Shell 编程三剑客。

grep

-n:表示显示行号
-i:表示不区分大小写
-v:表示反向过滤
[ ]: 查找集合字符

示例

过滤包含the的内容
过滤不包含the的内容
正则表达式与常用文本处理工具_第1张图片
过滤以sh开头,以rt结尾,中间匹配i或o
在这里插入图片描述
过滤oo前面不是w的内容和以不是w为开头的接着oo的内容
正则表达式与常用文本处理工具_第2张图片

sed

sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。sed 也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于 Shell 脚本中,用以完成各种自动化处理任务。
sed 的工作流程主要包括读取、执行和显示三个过程。
读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
执行:默认情况下,所有的 sed 命令都在缓冲区中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
显示:发送修改后的内容到输出流。在发送数据后,缓冲区将会被清空。
在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。
注意:默认情况下所有的 sed 命令都是在缓冲区内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

sed 命令

常见用法

sed [选项] '操作' 参数
sed [选项] -f scriptfile 参数

常见的 sed 命令选项主要包含以下几种

-e script(脚本命令) : 指定sed编辑命令
-f scriptfile(文件) : 指定的文件中是sed编辑命令
-h 或 --help :显示帮助
-n,--quiet 或 silent :表示仅显示处理后的结果
-i :直接编辑文本文件(会对文件产生变化)

常见的操作包括以下几种

a: 增加,在当前行下面增加一行指定内容
c:替换,将选定行替换为指定内容
d:删除,删除选定的行
i:插入,在选定行上面插入一行指定内容
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以ASCII码输出。其通常与“-n”选项一起使用。(输出)
s:替换,替换指定字符
y:字符转换

示例

输出文件内容

输出第4行,或者3到5行。正则表达式与常用文本处理工具_第3张图片
输出偶数行;奇数行
正则表达式与常用文本处理工具_第4张图片
输出1到6行之间的偶数行,3到9行之间的奇数行
正则表达式与常用文本处理工具_第5张图片
输出包含the的所在行的行号(等号用来输出行号)
在这里插入图片描述

删除符合条件的文本

仅在外部输出删除,不会对源文件产生影响
删除2到4行
正则表达式与常用文本处理工具_第6张图片
删除以a-z小写字母为开头的内容
正则表达式与常用文本处理工具_第7张图片
删除以.为结尾的内容
正则表达式与常用文本处理工具_第8张图片
删除所有空行
正则表达式与常用文本处理工具_第9张图片

替换符合条件的文本

使用sed命令进行替换操作时需要用到s(字符串替换),c(整行/整块替换),y(字符替换)命令选项。
将文件中的所有the替换为THE
正则表达式与常用文本处理工具_第10张图片
将每行中的第2个l替换为L
正则表达式与常用文本处理工具_第11张图片
将文件中的所有的o删除(替换为空串)
正则表达式与常用文本处理工具_第12张图片
在包含the的每行行首插入#号
正则表达式与常用文本处理工具_第13张图片

迁移符合条件的文本

在使用sed命令迁移符合条件的文本时,常用到以下参数。

H:复制到剪切板
g,G :将剪切板中的数据覆盖/追加至指定行
w:保存为文件
r:读取指定文件
a:追加指定内容

将包含the的行迁移至文件末尾,{;}用于多个操作
正则表达式与常用文本处理工具_第14张图片
将第1-4行内容转移至第16行后
正则表达式与常用文本处理工具_第15张图片
将包含the的行另存为文件out.file
正则表达式与常用文本处理工具_第16张图片
在第三行前面插入一个新行,内容为New
正则表达式与常用文本处理工具_第17张图片
注:
\n 换行符,是另起一新行(光标换行)
\r 回车符,光标回到一旧行的开头(覆盖前一个)

egrep

匹配o至少出现一次或者以上次数的内容
正则表达式与常用文本处理工具_第18张图片
匹配以be为开头,t为结尾,中间可以是s或者为空的内容
正则表达式与常用文本处理工具_第19张图片
匹配以sh为开头,rt为结尾,中间可以是i或者o的内容
正则表达式与常用文本处理工具_第20张图片
匹配包含oo出现一次,或者一次以上的内容
正则表达式与常用文本处理工具_第21张图片

awk

概述

awk 从输入文件或者标准输入中读入信息,与 sed 一样,信息的读入也是逐行读取的。不同的是 awk 将文本文件中的一行视为一个记录,而将一行中的某一部分(列)作为记录中的一个字段(域)。为了操作这些不同的字段,awk 借用 shell 中类似于位置变量的方法, 用$1、$2、$3…顺序地表示行(记录)中的不同字段。另外 awk 用$0 表示整个行(记录)。不同的字段之间是通过指定的字符分隔。awk 默认的分隔符是空格。awk 允许在命令行中用“-F 分隔符”的形式来指定分隔符

格式

awk 选项 ‘模式或条件 {编辑指令}’ 文件1 文件2
awk -f 脚本文件 文件1 文件2

awk 包含几个特殊的内建变量(可直接用):

FS:指定每行文本的字段分隔符,默认为空格或制表位(等于-F)
NF:当前处理的行的字段个数
NR:当前处理的行的行号(序数)
$0:当前处理的行的整行内容
$n:当前处理行的第n个字段(第n列)
FILENAME:被处理的文件名
RS:数据记录分隔,默认为\n,即每行为一条记录

示例

按行输出文本

{print}大括号外面的往往都是对行操作,BEGIN后面肯定会跟大括号。

awk -F: '{print $1,$7}' /etc/passwd        --查找出在/etc/passwd所有文件信息的第1个,第7个字段内容
awk -F: '/^zjq/{print $1,$7}' /etc/passwd
awk -F: '/\/sbin\/nologin$/{print $1,$7}'  --查找出在/etc/passwd所有文件信息的第1个,第7个字段内容且以zjq为开头的和以/sbin/nologin结尾的内容
awk -F: 'NR==3{print $1,$7}' /etc/passwd  --输出第3行的第1第7个字段
awk '(NR%2)==1{print}' test.txt         --输出所有奇数行内容
awk '(NR%2)==0{print}' test.txt         --输出所有偶数行内容
awk '/^the/{print}' test.txt            --输出the开头的行
awk '/the$/{print}' test.txt            --输出the结尾的行
awk '/nologin$/{print}' /etc/passwd --输出以nologin结尾的行
awk '/^root/{print}' /etc/passwd         --输出以root开头的行
awk 'BEGIN{x=0};/\/bin\/bash$/{x++};END{print x}' /etc/passwd     --统计以/bin/bash结尾的行的行数,等同于grep -c "/bin/bash$" 
awk'BEGIN{x=0};/\/sbin\/nologin$/{x++};END{print x}' /etc/passwd  --统计以/sbin/nologin结尾的行的行数
awk 'BEGIN{RS=""};END{print NR}' test.txt      --统计以空行分割的文本段落数

按字段输出文本

awk '{print $1,$7}' /etc/passwd         --输出每行(以空位或制表位分割)中第1、7个字段
awk -F ":" '$2==""{print}' /etc/shadow    --输出密码为空的用户记录
awk -F: '$2=="!!"{print}' /etc/shadow     --输出密码被锁定的用户记录
awk 'BEGIN{FS=":"};$2="!!"{print}' /etc/shadow   --查看密码被锁定的用户记录
awk -F: '($7~"/bash"){print $1}' /etc/passwd     --查看第7个字段中包含/bash的行的第一个字段
awk '(NF==8)&&($1~"nfs"){print $1,$2}' /etc/services     --查看一共8个字段且第一个字段中包含nfs的行的第1和2字段
 awk -F: '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd     --查看第7个字段不是/bin/bash也不是/sbin/nologin的行

通过管道、双引号调用 Shell 命令

 awk -F: '/bash$/{print | "wc -l"}' /etc/passwd        --调用wc -l命令统计使用bash的用户个数,等同于grep -c "bash$" 
w
awk 'BEGIN{while("w" | getline)n++;{print n-2}}'       --调用w命令统计在线用户数
awk -F. 'BEGIN{"hostname" | getline;print $1}'         --调用hostname命令,输出当前主机名

你可能感兴趣的:(LINUX,linux,shell)