正则表达式三剑客之——grep和sed
目录
一.grep
1.1定义
1.2核心功能
1.3基本语法
1.4常用选项
二.sed
2.1 定义
2.2 工作原理
2.3 基本语法
2.3.1常用选项
2.3.2sed自身脚本语法
1. 基本组成
2. 地址
3. 命令
2.3.3 sed替换查找
1 基本语法
2.sed替换查找的实例
3.分组+后向引用
4 变量调用
三.练习
一.grep
1.1定义
grep 是一个命令行工具,用于在文本文件中搜索指定的模式(通常是字符串或正则表达式),并输出匹配的行。
1.2核心功能
- 文本搜索:在文件中查找包含指定模式的行。
- 模式匹配:支持基本字符串匹配和正则表达式匹配。
- 灵活输出:可以输出匹配的行、行号、文件名,或者统计匹配的行数等。
1.3基本语法
grep [选项]… 查找条件 目标文件
- 查找条件:要搜索的字符串或正则表达式。
目标文件
:要搜索的文件(可以是多个文件)。选项
:用于控制grep
的行为(如忽略大小写、递归搜索等)
1.4常用选项
选项 | 功能 | 示例 |
---|---|---|
-i | 忽略大小写匹配 | grep -i "hello" file.txt (匹配 hello 、Hello 、HELLO 等) |
-v | 反向匹配,输出不包含模式的行 | grep -v "hello" file.txt (输出不包含 hello 的行) |
-r | 递归搜索目录 | grep -r "hello" /path/to/dir (在目录及其子目录中搜索) |
-R | 递归目录,但处理软链接 | grep -R "hello" /path/to/dir(在 /path/to/dir 及其子目录中递归搜索 "hello" ,并跟随符号链接。) |
-n | 显示匹配行的行号 | grep -n "hello" file.txt (输出匹配行及其行号) |
-m | 最多输出的匹配行数。 | grep -m 3 "hello" file.txt(输出前 3 个匹配的行,然后停止搜索。 |
-c(count) | 统计匹配的行数 | grep -c "hello" file.txt (输出匹配 hello 的行数) |
-E | 使用扩展正则表达式(等同于 egrep ) | |
-F | 不支持正则表达式,相当于fgrep | |
-w | 匹配整个单词 | grep -w "hello" file.txt (只匹配单词 hello ,不匹配 helloworld ) |
-o( --only-matching) | 只输出匹配的部分,而不是整行 | grep -o "hello" file.txt (只输出 hello ,而不是整行) |
-l | 只显示包含匹配模式的文件名 | grep -l "hello" *.txt (输出包含 hello 的文件名) |
-L | 只显示不包含匹配模式的文件名 | grep -L "hello" *.txt (输出不包含 hello 的文件名) |
-A | 显示匹配行及其后若干行 | grep -A 2 "hello" file.txt (输出匹配行及其后 2 行) |
-B | 显示匹配行及其前若干行 | grep -B 2 "hello" file.txt (输出匹配行及其前 2 行) |
-C | 显示匹配行及其前后若干行 | grep -C 2 "hello" file.txt (输出匹配行及其前后 2 行) |
-e | 指定多个模式 | grep -e "hello" -e "world" file.txt (匹配 hello 或 world ) |
-f | 从文件中读取模式 | grep -f patterns.txt file.txt (从 patterns.txt 中读取模式进行匹配) |
-q | 静默模式,不输出任何内容,仅通过退出状态码表示是否匹配 | grep -q "hello" file.txt (匹配成功返回 0,失败返回 1) |
--color=auto | 高亮显示匹配的部分 | grep --color=auto "hello" file.txt (匹配的 hello 会高亮显示) |
-h | 不显示文件名(当搜索多个文件时) | grep -h "hello" file1.txt file2.txt (只输出匹配行,不显示文件名) |
-H | 显示文件名(默认行为,当搜索多个文件时) | grep -H "hello" file1.txt file2.txt (输出匹配行及其文件名) |
-s | 忽略错误信息(如文件不存在) | grep -s "hello" non_existent_file.txt (不显示错误信息) |
二.sed
2.1 定义
sed 是一个非交互式的流编辑器,它从输入流(如文件或管道)中逐行读取文本,根据用户指定的命令对文本进行处理,然后将结果输出到标准输出(默认是终端)。sed 不会直接修改原始文件,除非明确指定。
2.2 工作原理
sed 的核心是逐行处理文本。它的工作流程如下:
-
读取一行:从输入流中读取一行文本,并将其存储在模式空间(Pattern Space)中。
-
应用命令:对模式空间中的文本应用用户指定的命令(如替换、删除、插入等)。
-
输出结果:将处理后的文本输出到标准输出。
-
循环处理:重复上述步骤,直到所有行都被处理完毕。
模式空间(Pattern Space):
- 用于存储当前正在处理的行。
- 所有的
sed
命令都是对模式空间中的文本进行操作。
2.3 基本语法
sed [option]... 'script;script;...' [input file...]选项 自身脚本语法 支持标准输入管道
2.3.1常用选项
选项 | 说明 |
---|---|
-n | 禁止自动输出,只打印被 p 命令处理的行。 |
-e | 指定多个脚本命令。 |
-f FILE | 从脚本文件中读取命令。 |
-i | 直接修改文件内容(原地编辑)。 |
-r或-E | 使用扩展正则表达式(默认是基本正则表达式)。 |
-s | 将输入文件视为多个独立的文件处理。 |
-i.bak | 备份文件并原处编辑 |
2.3.2sed自身脚本语法
1. 基本组成
sed 脚本由一系列命令组成,每个命令通常包括以下部分:
-
地址(可选):指定命令作用的目标行。
-
命令:定义要执行的操作。
-
参数(可选):命令所需的额外信息。
2. 地址
地址用于指定命令作用的目标行。可以是行号、正则表达式或范围。
地址类型 | 格式 | 说明 |
---|---|---|
单行地址 | 指定命令作用于某一行。 | |
n | 第 n 行(n 是行号,从 1 开始)。 | |
$ | 最后一行。 | |
/模式/ | 匹配正则表达式 模式 的行。 | |
范围地址 | 指定命令作用于一个范围内的行。 | |
起始行,结束行 | 从 起始行 到 结束行 之间的行。 | |
/模式1/,/模式2/ | 从匹配 模式1 的行到匹配 模式2 的行。 | |
起始行,+n | 从 起始行 开始的 n 行。 | |
起始行,~n | 从 起始行 开始,每隔 n 行处理一次。 | |
组合地址 | 通过逻辑组合多个地址,指定更复杂的目标行。 | |
地址1;地址2 | 对 地址1 和 地址2 都执行命令。 | |
地址1,地址2! | 对不在 地址1 和 地址2 之间的行执行命令。 | |
特殊地址 | sed 提供了一些特殊地址,用于处理特定的行。 | |
1~n | 从第 1 行开始,每隔 n 行处理一次。 | |
n~m | 从第 n 行开始,每隔 m 行处理一次。 | |
0,/模式/ | 从第 1 行到匹配 模式 的行。 |
3. 命令
命令 | 说明 |
---|---|
d | 删除匹配的行。 |
p | 打印匹配的行。 |
Ip | 忽略大小写输出 |
! | 模式空间中匹配行取反处理 |
i\ | 将指定的文本插入到匹配到的行前面。 |
a\ | 将指定的文本添加到匹配到的行后面。 |
c\ | 替换行为单行或多行文本 |
r file | 将文件内容插入到当前行后。 |
w file | 保存模式,将当前行写入文件。 |
q | 退出 sed 处理。 |
= | 为模式空间中的行打印行号 |
i | 在当前行前插入文本。 |
s | 替换文本。(更详细的在下面sed替换查找中) |
1.sed '1d' file.txt
删除 file.txt 的第一行。2.sed -n '/pattern/p' file.txt
只打印包含 pattern 的行。3.sed -n '/pattern/Ip' file.txt
忽略大小写并打印包含 pattern 的行。4.sed '/pattern/!d' file.txt
删除不包含 pattern 的行。5.sed '/pattern/i\new line' file.txt
在包含 pattern 的行之前插入 new line。6.sed '/pattern/a\new line' file.txt
在包含 pattern 的行之后追加 new line。7.sed '/pattern/c\new line' file.txt
将包含 pattern 的行替换为 new line。8.sed '/pattern/r otherfile.txt' file.txt
在包含 pattern 的行之后插入 otherfile.txt 的内容。9.sed '/pattern/w output.txt' file.txt
将包含 pattern 的行写入 output.txt。10.sed '/pattern/q' file.txt
在遇到包含 pattern 的行后退出。11.sed '/pattern/=' file.txt
打印包含 pattern 的行的行号。12.sed 's/old/new/' file.txt
将 old 替换为 new。13.sed '/pattern/i\new line' file.txt
在包含 pattern 的行之前插入 new line。14.sed 's/old/new/' file.txt
将 old 替换为 new。
2.3.3 sed替换查找
1 基本语法
sed 's/要查找的内容/替换的内容/修饰符' 文件名
# '/'为分隔符,可以用'@' 或者 '#'
# 要查找的内容可以用正则表达式
# 替换的内容无法用正则表达式# 修饰符 #
g 行内全局替换
p 显示替换成功的行
w /PATH/FILE 将替换成功的行保存至文件中
I,i 忽略大小写
2.sed替换查找的实例
示例 1:简单替换
将每行的第一个 foo 替换为 bar:
sed 's/foo/bar/' input.txt示例 2:全局替换
将每行的所有 foo 替换为 bar:
sed 's/foo/bar/g' input.txt示例 3:忽略大小写替换
将每行的所有 foo(忽略大小写)替换为 bar:
sed 's/foo/bar/gi' input.txt示例 4:打印替换后的行
仅打印替换后的行:
sed -n 's/foo/bar/p' input.txt示例 5:将替换后的行写入文件
将替换后的行写入 output.txt
sed 's/foo/bar/w output.txt' input.txt
3.分组+后向引用
1. 分组
分组是指用括号 ()
将一部分正则表达式括起来,形成一个子表达式。分组的作用包括:
- 捕获匹配的文本:将括号内的内容作为一个整体匹配,并捕获结果。
- 应用量词:对分组内的内容应用量词(如
*
、+
、?
等)。 - 逻辑分组:将多个字符或表达式作为一个整体处理。
2. 后向引用
后向引用是指在正则表达式中引用之前捕获的分组内容。在 sed
中,后向引用使用 \1
、\2
、\3
等表示,分别对应第 1 个、第 2 个、第 3 个分组。
echo "hello world" | sed 's/\(hello\) \(world\)/\2 \1/'\(hello\) 是第 1 个分组,捕获 hello。
\(world\) 是第 2 个分组,捕获 world。
\2 \1 表示将第 2 个分组和第 1 个分组交换位置。#将hello world中的hello和world分组,并交换位置echo "hello hello world world" | sed 's/\([a-z]\+\) \1/\1/g's/.../.../:sed 的替换命令,用于查找并替换文本。
\([a-z]\+\):
\(...\):分组,捕获括号内的内容。
[a-z]\+:匹配一个或多个小写字母。
整体表示捕获一个单词(由小写字母组成)。
\1:
\1:后向引用,引用第 1 个分组捕获的内容。
整体表示匹配一个空格后跟第 1 个分组捕获的单词。
/\1/:替换为第 1 个分组捕获的内容。
g:全局替换,替换所有匹配项。#将连续重复的单词替换为单个单词
4 变量调用
sed允许使用变量来替代文本中的特定部分。
在 sed
中使用变量时,需要注意以下几点:
- 变量替换:变量需要在
sed
脚本之外定义,并通过双引号"
传递给sed
。 - 特殊字符:如果变量中包含特殊字符(如
/
、\
等),需要对其进行转义。 - 单引号与双引号:
- 单引号 ':
sed
脚本中的内容会被视为字面量,变量不会被替换。 - 双引号
"
:sed
脚本中的变量会被替换为其值。
- 单引号 ':
示例 1:简单变量替换
将文本中的 foo 替换为变量 $var 的值:
var="bar"
echo "foo foo foo" | sed "s/foo/$var/g"示例 2:变量中包含特殊字符
如果变量中包含 /,需要对其进行转义:
var="path/to/file"
echo "Replace this: /path/to/file" | sed "s#/path/to/file#$var#g"
输出:Replace this: path/to/file
这里使用 # 作为分隔符,避免与 / 冲突。示例 3:多变量替换
将文本中的 foo 和 bar 分别替换为变量 $var1 和 $var2 的值:
var1="hello"
var2="world"
echo "foo bar" | sed "s/foo/$var1/; s/bar/$var2/"
输出:hello world示例 4:变量作为查找模式
使用变量作为查找模式:
pattern="foo"
echo "foo bar foo" | sed "s/$pattern/replaced/g"
三.练习
1找出/etc/passwd 文件中root 开头的行
grep "^root" /etc/passwd2找出/etc/passwd 含有root 的行
grep "root" /etc/passwd3找出/etc/passwd 文件中 root开头或 mail 开头的行
grep -e "^root" -e "^mail" /etc/passwd
grep "^root|^mail" /etc/passwd4过滤出 /etc/passwd文件中已bin开头的行,并显示行号
grep -n "^bin" /etc/passwd5过滤掉/etc/passwd文件中 root开头的行
grep -v "^root" /etc/passwd6.在当前目录下所有.cc 的文件中找到含有“luckyboy”内容的文件:
find -type f -name '*.cc' | xargs grep -l "luckyboy"
find -type f -name '*.cc' -exec grep -l "luckyboy" {} \;
-l --file-with-matches # 列出文件内容符合指定的范本样式的文件名称
-r 递归查询7.找出当前目录下包含127.0.0.1关键字的文件
grep '127.0.0.1' `find . -type f `
sed -n '/127.0.0.1/p' `find . -type f`
awk '/127.0.0.1/' `find . -type f`8.删除或显示1.file 文件第3行到第7行的内容
删除:
sed -i '3,7d' 1.file
awk '(NR>=3&&NR<=7)' 1.file 把第三行到第七行排除
显示:
sed -n '3,7p' 1.file
awk 'NR>=3 && NR<=7' 1.file9.从文件1.file中提取第3行到第7行的内容
sed -n '3,7p' 1.file
awk 'NR==3,NR==7' 1.file
awk 'NR>=3 && NR<=7' 1.file
head -7 1.file | tail -510.使用awk取出/etc/passwd第一列数据也就是取出用户名。
awk -F : '{print $1}' /etc/passwd
sed 's#:.*$##g' /etc/passwd11.用命令行更改config.txt文件,把里面所有的“name”更改为“address”
sed -i 's#name#address#g' config.txt
vim config.txt:%s#name#address#g
awk '{gsub(/name/,""address)}1' config.txt12.写出查询file.txt以abc结尾的行
grep 'abc$' file.txt
sed -n '/abc$/p' file.txt
awk '/abc$/' file.txt13.删除file.txt文件中的空行
grep -v '^$' file.txt
sed '/^$/d' file.txt
awk '!/^$/' file.txt
文件中的空行可能是只有空格的行:
grep -v '^ *$' file.txt
sed -n '/^ *$/p' file.txt
awk '/^ *$/' file.txt14.打印file.txt文件中的第10行
sed -n '10p' file.txt
head -10 file.txt| tail -1
awk 'NR=10' file.txt15.删除/etc/fstab文件中所有以#开头的行,行首的#号及#后面的所有空白字符
sed -i '/^#/ s/^#[[:blank:]]*//' /etc/fstab16.查找最后修改时间是3天前,后缀是*.log的文件并删除
find /tmp/ -type -f -mtime -3 -name "*.log" | xargs rm -f
find /tmp/ -type -f -mtime -3 -name "*.log" -exec rm -f {} \;
find /tmp/ -type f -mtime +3 -name '*.log' -exec rm {} +\; -exec find 命令找出 1 个文件就把文件放在{}的位置
+;如果-exec后面使用+ find会把前面找到的所有文件1次性的放在{}所在位置17.查找文件2.txt中1到20行之间,同时将"aaa"替换为"AAA",“ddd"替换"DDD”
sed '1,20y/ad/AD/' 2.txt
sed -ne 's#a#A#g;s#d#D#g;1,20p' 2.txt 18.使用sed命令打印出文件的第一行到第三行
sed -n '1,3p' file.txt
awk 'NR>=1&&NR<=3' file.txt
head -3 file.txt19.在/var/sync/log/cef_watchd-20080424.1og文件中查找大小写不敏感“mysql"字符串中的命令是:
grep -iw 'mysql' /var/sync/log/cef_watchd-20080424.1og20.把data目录及其子目录下所有以扩展名.txt结尾的文件中包含oldgirl的字符串全部替换为oldboy.
sed -i 's#oldgirl#oldboy#g' `find /data/ -type f -name '*.txt'`21.查看linux服务器ip的命令,同时只显示包含ip所在的行打印出来
ip a s ens33 | sed -n '3p' | sed -r 's#^.*t ([0-9].*)/.*$#\1#g'
ip a s ens33 | sed -n '3p' | awk '{print $2;}' | awk -F / '{print $1;}'
sed语法:-r 使用正则表达式 22.用awk获取文件中第三行的倒数第二列字段
awk 'NR==3{print $(NF-1)}' file.txt23.请用shell查询file1里面空行的所在行号
grep -n '^$' file.txt
awk '/^$/{print NR,$0}' file1.txt24.显示file文件里匹配foo字串那行以及上下5行、显示foo及前5行、显示foo及后5行
grep -A5 'foo' file.txt 后5行
grep -B5 'foo' file.txt 前5行
grep -C5 'foo' file.txt 上下5行25.查找file.log文件中的包含关键字“helloworld”的内容,及其上下两行的内容重定向保存到1.txt
grep -C2 'helloworld' file.log >> 5.txt26.当前系统中没有任何文本编辑器(vi,emacs,vim,edit等),如何过滤掉注释行和空行查看/etc/ssh/sshd_config文件
sed -r '/^#|^$/d' /etc/ssh/sshd_config
awk '!/^$|^#/' /etc/ssh/sshd_config 27.从a.log文件中提取包含“WARNING”或“FATAL”,同时不包含“IGNOR”行,然后,提取以“:”分割的第五个字段
awk -F: '/WARNING|FATAL/&&!/IGNOR/{print $5}'28.文件内容排序、文件行取唯一值的命令分别是
sort
uniq 除文件中的重复内容行29.在每一行后增加一空行?
sed ‘G’ test.txt30.在匹配regex的行之后插入一空行?
sed ‘/regex/G’ text.txt31.计算文件行数?
wc -l32.sed将文件test中第50行中的haiwao改为haiwai?
sed ‘50s/haiwao/haiwai/’ test33.替换一个文件/etc/passwd里的这root:x:0:0:root:/root:/bin/bash一行第二个root为test?
sed ‘/root/s/:root:/:test:/’ /etc/passwd34.打印/etc/passwd的奇数行?
sed -n ‘1~2p’ /etc/passwd