grep
awk
sed
linux 三剑客概述
grep、sed、awk是linux操作文本的三大利器,合称文本处理三剑客,也是必须掌握的linux命令之一。
三者的功能都是处理文本,但侧重点各不相同:
- grep擅长查找功能
- awk擅长取列
- sed擅长取行和替换
类比sql:
grep=select * from table
awk=select field from table
sed=update table set field=new where field=old
grep
也可参看 linux进阶之正则表达式
语法
grep [options] pattern [file...]
工作方式
在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容
常用选项 option
选项 | 描述 |
---|---|
-i | 忽略大小写。不会区分大小写字符。也可用--ignore-case 来指定。 |
-v | 打印不匹配的行,。通常,grep 程序会打印包含匹配项的文本行。这个选项导致 grep 程序 只会不包含匹配项的文本行。也可用--invert-match 来指定。 |
-c | 打印匹配的数量(或者是不匹配的数目,若指定了-v 选项),而不是文本行本身。 也可用--count 选项来指定。 |
-o | 把每个匹配的内容用独立的行来打印 |
-E | 使用扩展的正则表达式,等价与egrep(除 \( \) \b 外,使用其他正则都可以去掉转义符\ ) |
-r | 递归搜索,搜索当前目录和子目录,此参数的效果和指定“-d recurse”参数相同 |
-e | 实现多个选项间的逻辑or关系 |
常用pattern正则表达式
- 元字符
^ $ . [ ] { } - ? * + ( ) | \
- 点.匹配任意字符,+ ⼀个或者多个,* 0个或多个,?匹配零次或一次,匹配特定个数的元素{n,m}
- 锚点^ $,插入符号和美元符号被看作是锚点。这意味着正则表达式只有在文本行的开头或末尾被找到时,才算发生一次匹配;
- 中括号表达式和字符类[]中括号表达式,能够指定一个待匹配字符集合(包含在不加中括号的情况下会被解释为元字符的字符);
- 否定,在中括号表示式中的第一个字符是一个插入字符^,则剩余的字符被看作是不会在给定的字符位置出现的字符集合;
- 字符区域-,如[A-Za-z0-9];
更多用法请参看正则表达式和linux进阶之正则表达式
举例
# 忽略大小写,不显示匹配的行
curl https://1eq066.coding-pages.com 2>/dev/null | grep -i linux
# 匹配的行
curl https://1eq066.coding-pages.com | grep -o 'https://[a-zA-Z0-9\.\-]*'
# 扩展正则表达式
curl https://1eq066.coding-pages.com | grep -o - E 'https://[a-zA-Z0-9.-]*'
grep -A -B -C pattern file 打印命中数据的上下⽂
awk
awk(来自创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母),awk其实不仅仅是工具软件,还是一种编程语言,被定义为“样式扫描和处理语言”。
它适合文本处理和报表生成,其语法较为常见,借鉴了某些语言的一些精华,如 C 语言等。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
处理的数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。
mac上的awk与linux略有区别,有些语法不支持,可安装gawk
语法
awk [options] 'pattern{action}'
注意必须使用单引号''及包围的范围和{}
工作方式
awk是逐行处理,当awk处理一个文本时,会一行一行进行处理,处理完当前行,再处理下一行,awk默认以"换行符"为标记,awk会按照用户指定的分割符去分割当前行,如果没有指定分割符,默认使用空格作为分隔符。
内置变量
内置变量 | 说明 |
---|---|
FS(Field Separator) | 字段分隔符, 默认为空格,如BEGIN{FS="xxx"} |
OFS(Out of Field Separator) | 输出数据的字段分隔符 |
RS(Record Separator) | 记录行分隔符,可以理解为找到某某标志,让每个某某后的内容重新变成一行 |
ORS(Output Record Separate) | 输出字段的⾏分隔符,可以理解为RS的逆向过程 |
NF(Number of Field) | 字段数(列) ,即一个文本文件中一行(一条记录)中的字段个数 |
NR(Numner of Record) | 记录数(行),即处理的文本文件的行数(记录数) |
$ echo i----love----you | awk 'BEGIN{ FS="----";OFS="*****" }{ print $1,$2,$3 }'
i*****love*****you
$ echo a|b|c | awk 'BEGIN{ RS="|"; } { print $0 }'
a
b
c
常用选项option
- -F 指定分隔符,可指定一个或多个
如果没有指定分割符,默认使用空格作为分隔符
- -v 设置变量
$ awk -va=1 '{print $1,$1+a}' log.txt
- -f
$ awk -f {awk脚本} {文件名}
常用模式pattern
-
BEGIN和END
awk 'BEGIN{} {action} END{}'
BEGIN 模式指定了处理文本之前需要执行的操作,END 模式指定了处理完所有行之后所需要执行的操作。通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果
-
正则匹配及字符串匹配
# 输出包含 "re" 的行 $ awk '/re/ ' log.txt
# 忽略大小写 $ awk 'BEGIN{IGNORECASE=1} /this/' log.txt
-
区间选择
awk '/aa/,/bb/'
-
字段匹配
# ~ 和 !~ 匹配正则表达式和不匹配正则表达式 # 输出第二列包含 "th",并打印第二列与第四列 # ~ 表示模式开始。// 中是模式 $ awk '$2 ~ /th/ {print $2,$4}' log.txt
-
取某一行
# 取第⼆⾏ awk 'NR==2' # 除第一行 awk 'NR>1'
$0、$N
和$NF
- $0 代表原来的⾏
- $1 代表第⼀列(第一个字段)
- $N 代表第N列
- $NF 代表最后1列
举例
# 多次awk,-F指定多个分割符,$0 $1...
echo $PATH | awk 'BEGIN{RS=":"}{print $0}' | awk -F '[/.]' '{print $1,$2,$3,$4}'
echo $PATH | awk 'BEGIN{RS=":"}{print $0}' | awk 'BEGIN{FS="/"}{print $1,$2,$3,$4}'
# BEGIN{FS=""} 指定多个分割符
echo $PATH | awk 'BEGIN{RS=":"}{print $0}' | awk 'BEGIN{FS="[/.]"}{print $1,$2,$3,$4}'
sed
sed(stream editor)是一种流编辑器,也是文本处理中非常重要的工具
语法
sed [options] '[addr] command' [file...]
- options:为选项,可选
- addr:sed 中的大多数命令之前都会带有一个地址,其指定了输入流中要被编辑的文本行。如果省略了地址, 然后会对输入流的每一行执行编辑命令
- command: 编辑命令
- file:需要搜索的文件,可以是多个文件
注意引号包含的范围
工作方式
sed 是一种流编辑器,它一次处理一行内容。主要用来自动编辑一个或多个文件, 简化对文件的反复操作。
处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(patternspace ),接着用sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使诸如"D"的特殊命令,那会在两个循环之间清空模式空间,但不会清空保持空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出或-i选项。
工作流程:
- sed默认不编辑原文件,而是逐行操作,复制一份到指定内存(pattern space,模式空间)
- pattern space内进行模式匹配,即和指定条件做匹配
不满足模式:输出到标准输出STDOUT
满足模式:进行指定的模式操作,再输出到STDOUT - 第二个特殊的内存空间 :保持空间(hold space),临时保存操作在另一处内存
- 当执行pattern space和 hold space相关选项时候会进行之间的数据流编辑操作
- 最后根据操作执行hold space空间操作,选择性显示到STDOUT
option常用选项
选项 | 解释 |
---|---|
-n或--quiet或--silent | 不输出模式空间内容到屏幕,即不自动打印,只打印匹配到的行 |
-e | 多点编辑,对每行处理时,可以有多个Script |
-f | 把Script写到文件当中,在执行sed时-f 指定文件路径,如果是多个Script,换行写 |
-r | 支持扩展的正则表达式 |
-i | 直接将处理的结果写入文件 |
-i.bak | 在将处理的结果写入文件之前备份一份 |
地址常用表示法
地址 | 说明 |
---|---|
n | 行号,n 是一个正整数。 |
$ | 最后一行。 |
/regexp/ | 所有匹配一个 POSIX 基本正则表达式的文本行。注意正则表达式通过 斜杠字符界定。选择性地,这个正则表达式可能由一个备用字符界定,通过\cregexpc 来 指定表达式,这里 c 就是一个备用的字符。 |
addr1,addr2 | 从 addr1 到 addr2 范围内的文本行,包含地址 addr2 在内。地址可能是上述任意 单独的地址形式。 |
first~step | 匹配由数字 first 代表的文本行,然后随后的每个在 step 间隔处的文本行。例如 1~2 是指每个位于偶数行号的文本行,5~5 则指第五行和之后每五行位置的文本行。 |
addr1,+n | 匹配地址 addr1 和随后的 n 个文本行。 |
addr! | 匹配所有的文本行,除了 addr 之外,addr 可能是上述任意的地址形式。 |
command常用选项
选项 | 解释 |
---|---|
a | 在指定行后面追加文本,支持使用\n实现多行追加 |
i | 在行前面插入文本,支持使用\n实现多行追加 |
c | 替换行为单行或多行文本,支持使用\n实现多行追加 |
d | 删除模式空间匹配的行,并立即启用下一轮循环 |
n | 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令 |
s | 取代,替换指定字符 |
p | 打印当前模式空间内容,追加到默认输出之后 |
q | 退出Sed |
r | 读取指定文件的文本至模式空间中匹配到的行后面 |
w | 保存模式匹配的行至指定文件 |
= | 为模式空间中的行打印行号 |
! | 模式空间中匹配行取反处理 |
s/// | 查找替换,/为习惯使用分割符,也支持使用其它分隔符,如:s@@@,s###,s:::。加g表示行内全局替换;在替换时,可以加以下下命令,实现大小写转换 \l:把下个字符转换成小写;\L:把replacement字母转换成小写,直到\U或\E出现;\u:把下个字符转换成大写;\U:把replacement字母转换成大写,直到\L或\E出现;\E:停止以\L或\U开始的大小写转换 |
举例
- 常用选项示例
[root@jerry ~]# cat demo
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed "/aaa/p" demo #匹配到的行会打印一遍,不匹配的行也会打印
aaa
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed -n "/aaa/p" demo #-n不显示没匹配的行
aaa
[root@jerry ~]# sed -e "s/a/A/" -e "s/b/B/" demo #-e多点编辑
Aaa
Bbbb
AABBCCDD
[root@jerry ~]# cat sedscript.txt
s/A/a/g
[root@jerry ~]# sed -f sedscript.txt demo #-f使用文件处理
aaa
bbbb
aaBBCCDD
[root@jerry ~]# sed -i.bak "s/a/A/g" demo #-i直接对文件进行处理 g全部替换,否则只替换每行匹配到的第一个
[root@jerry ~]# cat demo
AAA
bbbb
AABBCCDD
[root@jerry ~]# cat demo.bak
aaa
bbbb
AABBCCDD
- 地址表示法 示例
[root@jerry ~]# cat demo
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed -n "p" demo #不指定行,打印全文
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed "2s/b/B/g" demo #替换第2行的b->B
aaa
BBBB
AABBCCDD
[root@jerry ~]# sed -n "/aaa/p" demo
aaa
[root@jerry ~]# sed -n "1,2p" demo #打印1-2行
aaa
bbbb
[root@jerry ~]# sed -n "/aaa/,/DD/p" demo
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed -n "2,/DD/p" demo
bbbb
AABBCCDD
[root@jerry ~]# sed "1~2s/[aA]/E/g" demo #将奇数行的a或A替换为E
EEE
bbbb
EEBBCCDD
- 编辑命令 示例
[root@jerry ~]# cat demo
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed "2d" demo #删除第2行
aaa
AABBCCDD
[root@jerry ~]# sed -n "2p" demo #打印第2行
bbbb
[root@jerry ~]# sed "2a123" demo #在第2行后加123
aaa
bbbb
123
AABBCCDD
[root@jerry ~]# sed "1i123" demo #在第1行前加123
123
aaa
bbbb
AABBCCDD
[root@jerry ~]# sed "3c123\n456" demo #替换第3行内容
aaa
bbbb
123
456
[root@jerry ~]# sed -n "3w/root/demo3" demo #保存第3行的内容到demo3文件中
[root@jerry ~]# cat demo3
AABBCCDD
[root@jerry ~]# sed "1r/root/demo3" demo #读取demo3的内容到第1行后
aaa
AABBCCDD
bbbb
AABBCCDD
[root@jerry ~]# sed -n "=" demo #=打印行号
1
2
3
[root@jerry ~]# sed -n '2!p' demo #打印除了第2行的内容
aaa
AABBCCDD
[root@jerry ~]# sed 's@[a-z]@\u&@g' demo #将全文的小写字母替换为大写字母
AAA
BBBB
AABBCCDD