Linux运维-SHELL编程之正则表达式与流编辑处理器
什么是正则表达式
正则表达式是一种用来描述字符序列的强大工具,通常用于字符串的匹配、搜索和替换操作。它由普通字符(例如字母、数字)和特殊字符(称为元字符)组成,通过这些元字符可以构建出具有特定模式的字符串。正则表达式在文本处理、数据提取、验证输入等方面都有广泛的应用。
我们可以理解为:正则表达式是一种字符串的抽象,代表符合某些要求的字符串的一个范式,在一般情况下只要满足了正则表达式的条件就会被认定为匹配成功
正则表达式基本内容
基本元字符
元字符 | 描述 |
---|---|
. |
匹配任意单个字符除了\n 与\r |
^ |
匹配字符串的开始 |
$ |
匹配字符串的结束 |
* |
匹配前面的字符零次或多次 |
+ |
匹配前面的字符至少一次或多次 |
? |
匹配前面的字符零次或一次 |
` | ` |
[] |
匹配括号内的所有字符,可在内部字符串首写^ 表示不匹配给定字符(例如[^ABC] ) |
[-] |
匹配在连续范围内的字符 |
[^] |
匹配不在该组内的字符 |
() |
表示一个子表达式 |
{n} |
匹配时指定前面字符出现的重复次数必须为n |
{n,} |
匹配时指定前面字符出现的重复次数至少为n,也可以指定至多出现次数{n,m} |
\ |
转义字符,用于匹配特殊字符 |
\< |
匹配一个词组开头的字串 |
正则表达式的贪婪(greedy)与非贪婪(non-greedy)指的是匹配模式下的不同行为。
- 贪婪:正则表达式默认是贪婪的,即会尽可能匹配更多的字符。例如,对于正则表达式
a.*b
,如果用来匹配字符串aabb
,它会匹配整个字符串,而不是只匹配到第一个b
为止。- 非贪婪:通过在量词后面加上
?
可以实现非贪婪匹配,这样正则表达式会尽可能少的匹配字符。例如,对于正则表达式a.*?b
,如果用来匹配字符串aabb
,它会匹配到第一个ab
为止,而不是匹配整个字符串。在量词后面加上
?
可以使得量词变成非贪婪的,否则默认是贪婪的。
带反斜杠的元字符
元字符 | 描述 |
---|---|
\s |
用来匹配所有空白字符,包括换行符 |
\S |
用来匹配非空白符,不包括换行符 |
\w |
匹配字母,数字,下划线 |
\d |
用来匹配数字 |
分组与捕获元
在正则表达式中,分组和非捕获元是用来对子表达式进行分组或者控制匹配行为的元字符。
-
分组:使用圆括号
()
来创建一个分组,可以对其中的子表达式进行分组,并对整个分组应用量词。例如,(?:...)
是一个非捕获分组,不会捕获匹配的内容,而(abc)
是一个捕获分组,会捕获匹配的内容以便后续使用。 -
非捕获元:用于对子表达式进行分组但不捕获匹配的内容。它可以避免将匹配的内容存储在匹配结果中,仅用于分组或者应用量词。
非捕获元 | 捕获元描述 |
---|---|
(?:exp1) |
捕获 exp1,但不记住匹配项。这在需要分组,但不需要捕获匹配内容时很有用。 |
(?=exp1) |
匹配 exp1 前面的位置,但不消费任何字符。这称为正向先行断言。例如,(?=\d) 匹配一个数字前面的位置,但不匹配数字本身。 |
(?!exp1) |
匹配后面跟的不是 exp1 的位置。这称为负向先行断言。例如,(?!\d) 匹配后面不是数字的位置。 |
(?<=exp1) |
匹配 exp1 后面的位置,但不消费任何字符。这称为正向后行断言。例如,(?<=\d) 匹配一个数字后面的位置,但不匹配数字本身。 |
(?<!exp1) |
匹配前面不是 exp1 的位置。这称为负向后行断言。例如,(?<!\d) 匹配前面不是数字的位置。 |
可以通过索引来引用。在使用捕获元时,可以通过
\1
、\2
等来引用先前捕获的内容。
修饰符
修饰符 | 描述 |
---|---|
i |
执行对大小写不敏感的匹配。 |
m |
多行模式。改变 ^ 和 $ 的行为,使它们分别在行的起始和结束处匹配,而不是在整个输入字符串的起始和结束处匹配。 |
s |
单行模式。改变 . 的行为,使其匹配所有字符,包括换行符 \n 。 |
g |
全局模式。查找所有匹配项,而不是在找到第一个匹配项后停止。 |
正则表达式匹配实例
- 匹配一个有效的IPv4地址,匹配形如
192.168.1.1
的IPv4地址:
regex
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
- 匹配一个日期(YYYY-MM-DD),匹配形如
2024-04-01
的日期:
regex
^\d{4}-\d{2}-\d{2}$
- 匹配一个有效的邮箱地址,匹配形如
example@example.com
的邮箱地址:
regex
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
- 匹配一个简单的HTML标签(不考虑属性),匹配形如
<div>content</div>
的简单HTML标签:
regex
<[a-zA-Z][a-zA-Z0-9]*>(.*?)<\/[a-zA-Z][a-zA-Z0-9]*>
- 匹配一个简单的URL(不考虑协议、端口和查询参数),匹配形如
http://example.com
的简单URL:
regex
^(http|https):\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/\S*)?$
在之前的文章中我们介绍过
[[...]]
可以使用正则表达式:
shellif [[ "$string" =~ pattern ]]; then echo "Matched" fi
但是正则表达式使用更常见的地方并不在于此,而是流编辑处理器
文本查找工具grep
grep
是一个强大的文本搜索工具,常用于在文件中查找特定模式的文本行。以下是 grep
命令的一些常见用法:
-
基本用法:在文件中搜索指定模式的文本行。
bashgrep 'pattern' file.txt
-
递归搜索:在指定目录及其子目录中递归搜索匹配的文本行。
bashgrep -r 'pattern' directory/
-
忽略大小写:在搜索时忽略模式的大小写。
bashgrep -i 'pattern' file.txt
-
显示匹配行数:显示匹配到的文本行的行数。
bashgrep -c 'pattern' file.txt
-
显示不匹配行:显示不包含匹配模式的文本行。
bashgrep -v 'pattern' file.txt
-
显示匹配文本:仅显示匹配到的文本,而不显示整行。
bashgrep -o 'pattern' file.txt
-
显示匹配行及上下文:显示匹配到的文本行及其上下文行。
bashgrep -C 2 'pattern' file.txt # 显示匹配行及其上下各两行
-
显示匹配行号:显示匹配到的文本行的行号。
bashgrep -n 'pattern' file.txt
-
限制搜索深度:在递归搜索时,限制搜索的深度。
bashgrep --max-depth=1 'pattern' directory/
-
扩展正则 :当使用
-E
选项时,grep
将以扩展的正则表达式语法进行匹配shellgrep -E 'pattern' file.txt
流编辑处理器sed
sed是一种在线的、非交互式的编辑器,它一次处理一行内容 。处理时,把当前处理的行存储在临时缓冲区中,称为模式空间(patternspace)。接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非使用重定向存储输出。Sed主要用来自动编辑一个或多个文件,简化了对文件的反复操作。
sed使用模式与常用选项
sed的使用模式一般是如下状态:
shell
sed 选项 命令 文件
选项 | 描述 |
---|---|
-e <script> |
将指定的 script 用作 sed 命令。 |
-f <file> |
从指定文件中读取 sed 脚本。 |
-i <suffix> |
直接在文件中进行编辑,并可选地备份原始文件,备份文件的后缀名由 suffix 指定。 |
-n |
不输出模式空间的内容,只有通过命令显式指定打印内容时才会输出。 |
-r 或 --regexp-extended |
使用扩展的正则表达式语法。 |
-s 或 --separate |
将输入视为多个独立的文件。 |
-u 或 --unbuffered |
使用无缓冲的输出。 |
-V 或 --version |
显示 sed 的版本信息。 |
-e
和-f
是用于指定sed
脚本的选项,但有一些区别:
-e <script>
:-e
选项允许在命令行上直接指定sed
脚本可以多次使用-e
选项,每次指定一个脚本,这些脚本将按照指定的顺序依次执行。例如:
shsed -e 's/abc/def/' -e 's/123/456/' input.txt
这将依次执行两个替换操作,第一个将
abc
替换为def
,第二个将123
替换为456
。
-f <file>
:-f
选项允许从指定的文件中读取sed
脚本。文件中的每一行都被视为一个sed
命令。例如,如果有一个名为script.sed
的文件包含以下内容:
shells/abc/def/ s/123/456/
可以像如下使用
-f
选项,这将会按照文件中的顺序依次执行两个替换操作:
shsed -f script.sed input.txt
我们接下来以如下文件来演示sed功能:
txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
sed删除文件中指定行
- 删除指令的基本格式如下,
d
表示执行删除操作
shell
sed 选项 '/匹配条件/d' 文件名
注意,为了防止在shell中出现冲突,最好是使用强解析即''
,避免造成命令歧义
- 删除符合正则匹配条件的行
shell
r123@localhost:~/shell_code$ sed -e '/commands/d' content.txt
Hello, World!
This is a test file for sed.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
- 删除指定行号的内容
shell
r123@localhost:~/shell_code$ sed -e '7d' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
- 删除指定行号范围内的行
shell
r123@localhost:~/shell_code$ sed -e '3,4d' content.txt
Hello, World!
This is a test file for sed.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
注意,这里的行号还可以用
$
来指定最后一行
shellr123@localhost:~/shell_code$ sed -e '$d' content.txt Hello, World! This is a test file for sed. It contains some sample text that can be used to test various sed commands. Feel free to modify this file and experiment with different sed commands. sed is a powerful stream editor. It can perform a wide range of text processing functions.
shellr123@localhost:~/shell_code$ sed -e '3, $d' content.txt Hello, World! This is a test file for sed.
sed替换文件中的指定内容
- 替换命令的格式如下,正则修饰符是可选的
shell
sed 选项 's/匹配条件/用于替换的字符串/[正则修饰符]' 文件名
我们以将所有sed替换为SED:
shell
r123@localhost:~/shell_code$ sed -e 's/sed/SED/g' content.txt
Hello, World!
This is a test file for SED.
It contains some sample text that can be uSED to test various SED commands.
Feel free to modify this file and experiment with different SED commands.
SED is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing SED!
/g
表示全局匹配,如果不加的话,只会替换每行中的第一个sed
shellr123@localhost:~/shell_code$ sed -e 's/sed/SED/' content.txt ... It contains some sample text that can be uSED to test various sed commands. ...
- 对匹配到的部分进行增加内容,即使用
&
表示匹配到的表达式
shell
r123@localhost:~/shell_code$ sed -e 's/sed/&SED/g' content.txt
Hello, World!
This is a test file for sedSED.
It contains some sample text that can be usedSED to test various sedSED commands.
Feel free to modify this file and experiment with different sedSED commands.
sedSED is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sedSED!
这种操作实质上是相当于使用了捕获元,只不过使用捕获元必须在扩展正则状态下:
shell
r123@localhost:~/shell_code$ sed -r 's/(sed)/\1SED/g' content.txt
Hello, World!
This is a test file for sedSED.
It contains some sample text that can be usedSED to test various sedSED commands.
Feel free to modify this file and experiment with different sedSED commands.
sedSED is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sedSED!
- 特殊情况下的匹配替换:存在
/
在字符串中时,我们必须将/
替换为#
shell
r123@localhost:~$ echo '/abc/344555/abc' | sed -e 's#abc#&ABC#g'
/abcABC/344555/abcABC
r123@localhost:~$ echo '/abc/344555/abc' | sed -e 's#abc#&ABC/g'
sed: -e expression #1, char 12: unterminated `s' command
r123@localhost:~$ echo '/abc/344555/abc' | sed -e 's/abc/&ABC/g'
/abcABC/344555/abcABC
sed从其他文件中添加内容
- 基本命令格式如下,不添加匹配条件时,默认添加到每一行后
shell
sed -e '[/匹配条件/]r 其他文件名' 当前文件名
- 在每一个符合匹配条件的行后增加文件内容
shell
r123@localhost:~/shell_code$ echo 12345678 > 1.txt
r123@localhost:~/shell_code$ sed -e '/sed/r 1.txt' content.txt
Hello, World!
This is a test file for sed.
12345678
It contains some sample text that can be used to test various sed commands.
12345678
Feel free to modify this file and experiment with different sed commands.
12345678
sed is a powerful stream editor.
12345678
It can perform a wide range of text processing functions.
Enjoy testing sed!
12345678
- 在当前文件后追加新文件内容
shell
r123@localhost:~/shell_code$ sed -r '$r 1.txt' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
12345678
sed文件内容另存为操作
- 基本命令格式如下,不添加匹配条件时,默认另存整个文件
shell
sed -e '[/匹配条件/]w 其他文件名' 当前文件名
shell
r123@localhost:~/shell_code$ sed -e '/commands/w tmp.txt' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
r123@localhost:~/shell_code$ cat tmp.txt
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
- 另存指定行的内容
sed
r123@localhost:~/shell_code$ sed -e '1,3w tmp.txt' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
r123@localhost:~/shell_code$ cat tmp.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
sed追加内容到指定位置
- 基本命令格式如下,不添加匹配条件时,默认追加到每行之后
shell
sed -e '[/匹配条件/]a追加内容' 文件名
shell
r123@localhost:~/shell_code$ sed -e '/commands/a123456' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
123456
Feel free to modify this file and experiment with different sed commands.
123456
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
- 追加内容到指定范围的行后
shell
r123@localhost:~/shell_code$ sed -e '3,5a123456' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
123456
Feel free to modify this file and experiment with different sed commands.
123456
sed is a powerful stream editor.
123456
It can perform a wide range of text processing functions.
Enjoy testing sed!
- 在一行后面追加多行内容
shell
r123@localhost:~/shell_code$ sed -e '1a 233\
23333\
233333 ' content.txt
Hello, World!
233
23333
233333
This is a test file for sed.
...
命令
i
与a
的操作几乎是一致的,不过i的作用是在指定行的前面添加内容,这与a
大同小异,故不多赘述:
shellr123@localhost:~/shell_code$ sed -e '3i123456' content.txt Hello, World! This is a test file for sed. 123456 It contains some sample text that can be used to test various sed commands. Feel free to modify this file and experiment with different sed commands. sed is a powerful stream editor. It can perform a wide range of text processing functions. Enjoy testing sed!
sed进行整行替换操作
- 基本命令格式如下,不添加匹配条件时,默认替换每一行
shell
sed -e '[/匹配条件/]c追加内容' 文件名
- 替换指定行号的内容
shell
r123@localhost:~/shell_code$ sed -e '2c 233333333' content.txt
Hello, World!
233333333
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
- 替换指定范围行号的内容为一行
shell
r123@localhost:~/shell_code$ sed -e '1,2c233333333' content.txt
233333333
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
sed操作目标行的下一行
我们使用{}
来包含多个命令来执行这一操作,n
用于指定下一行:
shell
sed 选项 '/匹配条件/{n;其他命令}' 文件名
shell
r123@localhost:~/shell_code$ sed -r '/commands/{n; d}' content.txt
Hello, World!
This is a test file for sed.
It contains some sample text that can be used to test various sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
sed命令反向操作文件
我们使用!
来让命令作用范围反向操作:
shell
r123@localhost:~/shell_code$ sed -e '/commands/!d' content.txt
It contains some sample text that can be used to test various sed commands.
Feel free to modify this file and experiment with different sed commands.
r123@localhost:~/shell_code$ sed -e '/commands/d' content.txt
Hello, World!
This is a test file for sed.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
sed执行多个操作的方式
- 使用多个
e
选项执行
shell
r123@localhost:~/shell_code$ sed -e '1d' -e '3d' content.txt
This is a test file for sed.
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
- 使用分号分割命令
shell
r123@localhost:~/shell_code$ sed -e '2d;3d' content.txt
Hello, World!
Feel free to modify this file and experiment with different sed commands.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
- 使用
{}
执行多个命令
shell
r123@localhost:~/shell_code$ sed -e '2,4{s/sed/&SED/g; s/commands/COMMANDS/g}' content.txt
Hello, World!
This is a test file for sedSED.
It contains some sample text that can be usedSED to test various sedSED COMMANDS.
Feel free to modify this file and experiment with different sedSED COMMANDS.
sed is a powerful stream editor.
It can perform a wide range of text processing functions.
Enjoy testing sed!
流编辑处理器awk
awk
是一种强大的文本处理工具,通常用于处理和分析文本文件中的数据。它以行为单位处理文本文件,可以根据指定的规则对文件进行处理和转换。awk
的基本工作流程是读取文件的每一行,将每一行拆分成字段(默认以空格分隔),然后应用用户定义的操作对字段进行处理。
awk
的基本结构如下:
bash
awk 'pattern { action }' filename
其中,pattern
是一个条件,用于指定何时执行action
,action
是要执行的操作。如果没有提供filename
,awk
将从标准输入读取数据。
例如,要打印一个文件的第一列,可以使用以下命令:
bash
awk '{ print $1 }' filename
这将打印文件中每一行的第一个字段(以空格分隔)。
注意:
awk
实质上是一种完整的编程语言,具有变量、数组、控制结构等基本编程元素。除了作为命令行工具使用外,awk
也可以编写独立的awk
脚本文件,其中包含更复杂的逻辑和功能。awk
提供了丰富的内置函数和特殊变量,使其在文本处理和数据转换方面非常强大和灵活。
awk的工作流程
awk
的工作流程通常如下:
- 读取文件 :
awk
从指定的文件或标准输入中逐行读取数据。 - 分割行:每行数据根据指定的分隔符(默认为空格)被拆分成多个字段。
- 匹配模式 :对每一行数据,
awk
根据用户提供的模式进行匹配。模式可以是简单的条件,也可以是正则表达式。 - 执行动作 :如果模式匹配成功,
awk
执行与模式关联的动作。动作可以是打印、计算、赋值等操作。 - 重复处理 :
awk
重复以上步骤,直到处理完所有输入数据。 - 输出结果 :根据执行的动作,
awk
将生成的结果输出到标准输出或指定的文件中。
在分割行时,awk实质上是先将当前读取到的行的数据储存在$0
,然后根据分割符将内容分组依次存储到$1
,$2
,...
awk的命令结构
shell
awk 选项 '命令' 文件名
选项 | 功能 |
---|---|
-F | 指定字段分隔符 |
-f | 指定awk 脚本文件 |
-v | 定义awk 变量 |
-i | 修改awk 的工作模式 |
-W | 控制awk 的警告消息 |
-o | 控制awk 的输出格式 |
-O | 控制awk 的输出字段 |
-F | 控制awk 的输入字段 |
awk的特殊模式
awk
中的BEGIN
和END
是特殊模式,用于在处理输入之前和之后执行一次性操作。
- 使用
BEGIN
在处理之前打印标题:
bash
awk 'BEGIN { print "Name\tAge\tGender" } { print $1 "\t" $2 "\t" $3 }' data.txt
这个命令在处理data.txt
之前会打印一行标题,然后对每一行数据打印第一、第二、第三个字段。
- 使用
END
在处理之后打印汇总信息:
bash
awk '{ total += $1 } END { print "Total: " total }' data.txt
注意:BEGIN
和END
块中的代码只会执行一次,分别在处理开始和结束时执行。
awk简单使用案例
shell
r123@localhost:~/shell_code$ sudo awk -F : 'BEGIN{ print "start"}{print $1" => "$2}END{print "end"}' /etc/passwd
start
root => x
daemon => x
bin => x
...
end
实质上使用的时候其他操作比较少见,sed就可以了,这里唯一需要注意的是,我们需要将其他的字符串以""
包括