文本三剑客
2025-09-23 09:51:51

文本三剑客

Linux下处理文本数据非常强大的三个程序

grep

grep是一个过滤器,通过指定条件过滤文本数据

egrep和greo -E 相等,都是开启正则表达式的支持。

语法:

grep [option] [pattern] [file, ...]

command | grep [...] ...

常用参数

-o 只显示匹配到的字符本身。

-v 不显示匹配行(反向匹配)

-i 匹配忽略大小写

-n 显示行号

-r 递归目录搜索

-E 支持正则表达式

-F 不按正则表达式匹配,按字符串字面意思匹配

了解参数

-c 只输出匹配行的数量,不输出匹配行

-w 匹配整词 不匹配包含的(精确匹配,前后有空格或tab)

-x 匹配整行 (同上)

-l 只列出匹配文件名,不显示匹配行数据(与-r搭配)

sed

sed是一个行(流)编辑器,非交互式的对文件进行增删改查操作。

使用者只能在命令行输入编辑命令,指定文件,然后再屏幕上查看输出。它和文本编辑器有本质区别

文本编辑器:编辑对象为文本文件

行编辑器:编辑对象为文本中的行

前者一次处理一个文本整体,而后者是处理文本中的行。

sed数据处理流程

文本行 -> 内存(缓存) -> 屏幕

数据在内存中被处理,然后默认输出到屏幕

也就是说默认情况下sed是修改的只是读到内存的文本行数据,不会修改源文本行

sed命令

语法:sed [options] '{command}[flage]' [filename]

command 内部命令

/abcd/ 匹配模式,在斜杠中写匹配字符

sed '/root/i\addTest' filename

将addTest插入到有root字符的行前。

  • a

a 在匹配后面插入:

sed 'aaddTest' filename

sed 'a\addTest' filename

将addTest字符串追加到file文件每行的后面。

这个两种写法都对,sed认为参数的第一个是命令,可以在a参数后面加\转义,一便区分。

  • i

i 在匹配前插入

sed 'i\addTest' filename

将addTest字符串插入到file文件每行的前面。

  • p

p 打印

sed 'p' filename

打印file文件,但每一行会打印两次,因为加p会打印文件内容,但默认会打印缓存的行,所以每一行会打印两边。

  • d

d 删除

sed '3d' filename

删除file文件的第三行

sed '3,5d' filename

删除file文件的第三行到第五行

sed '/root/d' filename

删除file文件的有root的一行

  • s

s 查找替换

sed 's/lisi/zhangsan/' filename

将file文件行的lisi替换为zhangsan

sed '/user/s/lisi/zhangsan/' filename

将file文件行有user字段的lisi替换为zhangsan

  • c

c 更改

sed 'c\addTest' filename

将file文件每行改为addTest

sed '3c\addTest' filename

将file文件第三行改为addTest

sed '2,5c\addTest' filename

注意2,5在c参数里与其他参数有区别,它会将2到5行视为一行,也就是将2到5行全部删除然后只插入一条addTest。

  • y

y 转换 N D P

sed 'y/abcd/ABCD' filename

将file文件行的a,b,c,d 转换为对于的A,B,C,D

注意!前面的第一个字符会被后面的一个字符代替,并不是一定要有关系也可以用其他任意字符代替前面的字符,只需要位置顺序相 同。

flags

数字 :表示新文本的替换模式

sed 's/lisi/zhangsan/' filename

我们在使用查找替换内部命令s的时候,如果这一行有两个lisi这条命令只会替换第一个lisi,后面的lisi并不会替换

sed 's/lisi/zhangsan/2' filename

此时就只会处理第二个lisi,而不会处理第一个或者其他位置的lisi

g :表示用新文本替换现有外部的全部实列

sed 's/lisi/zhangsan/g' filename

此时就会处理替换行内所有的lisi

p :表示打印内容

sed '3s/lisi/zhangsan/p' filename

将第三行替换的同时在打印一遍

w :将替换结果写入到文件

sed 's/lisi/zhangsan/w tmpfile' filename

将替换的行写入到tmpfile文件保存,源文件不变

options

-n 抑制输出,只打印我要求打印的

sed -n '3s/lisi/zhangsan/p' filename

只会打印我要求的(p参数)的行,其他行不打印

-e script

将脚本中指定的命令添加到处理输入时执行的命令中,多条件,一行中要有多个操作

sed -e 's/tmp/Tmp/;s/fish/bash/' filename

;区分多条命令。

-f script 将文件中指定的命令添加到处理时执行的命令当中。

在cmd文件中添加命令,一行一个,使用是指定即可执行

cmdfile内容:

3s/root/ooo/

/root/s/abc/bca/

使用命令:

sed -f cmdfile filename

即可使用cmd文件内的命令

-i 编辑文件内容(修改源文件)

sed -i 's/root/ooo/g' filename

此时会修改源文件,并且不会打印到屏幕上

-i.xxx 先备份文件以.xxx结尾在编辑文件内容(修改源文件)

sed -i.bak 's/root/ooo/g' filename

此时会先备份一份源文件文件名末尾是.bak,然后再修改源文件,并且不会打印到屏幕上。

推荐使用 -i.xx 以防万一改错了还能恢复。

-r 使用扩展的正则表达式

sed -n -r '/^(root)(.*)(fish)$/p' /etc/passwd

在匹配模式中使用正则表达式,打印以root开头中间除回车以外的任意字符(该字符不出现或出现多个 以fish结尾的行

内容:

root:x:0:0::/root:/bin/fish

! 取反,跟在模式条件后面(与shell有所区别)

命令总结

增: a(行后),i(行前)

i(将后面指定文件的内容追加到匹配的行后)

w(将结果另存文件)

删:d

改(部分):

s/pattern/string/(查找pat替换为string(默认只配一个))

s/patern/string/g(g表示行内全部匹配)

s/patern/string/2(2表示同行之匹配2个)

s/patern/string/ig(ig表示匹配时忽略大小写)

查:p(将结果打印)

小技巧

统计一个文件有多少行:

sed -n '$=' filename

打印file内容时加上行号

sed '=' filename


awk

简介

awk其实也是一种行编辑器,可以把数据截取,处理(运算),输出,功能十分强大。

awk的工作方式是读取数据将每一行数据视为一条记录(record)每条记录以字段分割符分成若干字段,然后输出各个字段的值。

语法

awk [options] [BEGIN]{program} [END][file]

优先级:BEGIN{} -> {program} -> END{}

program和END需要数据源不能脱离数据源执行。

BEGIN是在program之前处理的,它不需要数据源也可以执行如:

awk 'BEGIN{print "HelloWorld"}'

没有制定文件名有没有通过管道传输数据,就可以执行。

提取列

awk可以用与确认列的参数符

|参数|含义|

–|–

|$0|全部的列|

|$n|指定第n列如:$3(第三列|

|$NF|最后一列|

awk默认在行数据里是以空格分隔的

提取test文件全部列

1
2
3

awk '{print $0}' test

提取/etc/passwd文件每一行的第一列

因为此文件里列是以 : 分隔的所以指定分隔符使用 -F

awk -F ":" '{print $1}' test

还可以对列进行处理:

awk -F ":" '{print "User:"1, "Shell:" NF}' test

如果只想处理要第一行,可以使用NR==n来指定行。

awk -F ":" 'NR==1{print "User:"1, "Shell:" NF}' test


awk高级用法

awk就是一门语言,它拥有语言的特性,可以定义变量,数组,可以进行运算,流程控制。

定义变量:

awk 'NR==1{user=$1,print user}' passwd

结果:root

还可以使用 -v 定义变量

awk -v num=10 'BEGIN{print num}'

定义一个数组:

1
2
3
4
5
6
7

awk 'BEGIN{array[0]=root;array[1]=200;print array[0],array[1]}'

输出

root 200

awk运算符

赋值运算 =

比较运算 > >= == < <= !=

数学运算 + - * / % ** ++ --

逻辑运算 && ||

匹配运算 ~ !~

运算例子:

1
2
3
4
5

awk 'BEGIN{print 100>=2 && 1<=100}'

1 #打印

为真打印1,为假打印0

匹配例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#精确匹配

awk -F ":" '$1 == "root"{print $0}' passwd

精确不匹配

awk -F ":" '$1 != "root"{print $0}' passwd

模糊匹配

awk -F ":" '$1 ~ "ro"{print $0}' passwd

模糊不匹配

awk -F ":" '$1 !~ "ro"{print $0}' passwd

awk 环境变量

–|–

|FIELDWIDTHS|自定义列的宽度以确认列的分隔|

|FS|输入行中的列分隔符(与-F相同)|

|OFS|输出行中的列分隔符用于显示效果(默认空格)|

|RS|输入行的分隔符(默认行分隔符\n)|

|ORS|输出行的分隔符(默认分隔符\n)|

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

awk'BEGIN{FIELDWIDTHS="1 2 3"}NR==1{print1,2,$3}' file

#自定义列宽,以列宽确认列的分隔,第一列长度为1字符,第二列为2字符,第三列为3字符。

awk 'BEGIN{FS=":"}NR==1{print1,2,$3}'

#效果和-F ":"相同

awk 'BEGIN{OFS="-"}NR==1{print1,2,$3}' file

#$1$2$3之间不在是空格分隔而是“-”

awk 'BEGIN{RS=" "}{print1,2,$3}' file

#此时输出效果为[第1行 第2行 第3行]

#行与行之间不在进行换行

#都在一行中显示以自定义的空格来区分。

awk 'BEGIN{ORS}{print $0}' file

#现在输出在屏幕上的行末尾不在换行。


awk 流程控制

awk支持以下流程控制语句

if for while do ... while break

if

源式子:

seq 1 9 > num

awk '$1>5{print $0}' num

会打印$1大于5的行

用if写:

awk '{if($1>5)print $0}' num

注意if后面紧跟需要执行的语句,否则不认为和if有关联。

else:

awk '{if($1<5)print1*2;else print 1/2}' num

如果小于5就乘2打印,如果大于5就除2打印

for

seq 1 10 > num

awk -v num=0 '{num=num+$1}END{print num}' num

将每一行相加,最后打印结果为55

用for写:

cat num2

10 82 26

39 24 42

39 28 99

awk '{num=0;for(i=1;i<4;i++)num+=$i;print num}' num2

每行的列相加打印:

118

105

166

while

cat num2

10 82 26

39 24 42

39 28 99

awk '{num=0;i=1;while(i<4){num+=$i;i++}print num}' num2

打印:

118

105

166

do … while

cat num2

10 82 26

39 24 42

39 28 99

其实与while一样,只不过这种写法是先执行一次在判断,while是先判断在执行。

awk '{num=0;i=1;do{num+=$i;i++}while(i<4)print num}' num2

打印:

118

105

166

break

可在循环中搭配if跳出循环

cat num2

10 82 26

39 24 42

39 28 99

在循环中判断当num大于50时跳出循环

  • while-break

awk '{num=0;i=1;while(i<4){num+=$i;i++;if(num>50)break}print num}' num2

输出:

92

63

67

  • for-break

awk '{num=0;for(i=1;i<4;i++){num+=$i;if(num>50)break}print num}' num2

输出:

92

63

67


awk字符串处理函数

|函数名|解释|函数返回值|

–|–

|length(str)|计算字符串长度|整数长度值|

|index(str1,str2)|在str1中查找str2的下标|索引,从1计数|

|tolower(str)|转小写|转换后的str|

|toupper(str)|转大写|转换后的str|

|substr(str,m,n)|截取从str的m开始长度n|截取后的字符串|

|split(str,arr,fs)|按fs切割str结果存为arr|切割后的子串的个数|

|match(str,RE)|在str中查找RE位置|位置索引|

|sub(RE,RepStr,str)|将str中符合re的替换为repstr(只替换一个)|替换的个数|

|gsub(RE,RepStr,str)|将str中符合re的全部替换为repstr|替换个数|


awk小技巧

打印test文本的行数:

awk 'END{print NR}' test

打印test文本最后一行内容:

awk 'END{print $0}' test

打印test文本最后行的列数:

awk 'END{print NF}' test

打印指定行的列数:

awk 'NR==n{print NF}' num2


find 文件查找

find语法 :find ./ -name test.txt

find常用选项

常用选项:

-name 根据文件名搜索

-iname 根据文件名搜索(不区分大小写)

-user 搜索文件属主(用户名)的所有文件

-group 搜索文件属组(组名)的所有文件

-type :

find . -type f 文件

find . -type d 目录

find . -type c 字符设备文件

find . -type b 块设备文件

find . -type l 链接文件

find . -type p 管道文件

-size :

find . -size -nc 小于n字节的文件

find . -size +nM 大于1M的文件

find . -size nk 等于nKb的文件

不建议使用精准匹配大小,有很多问题。

-mtime :

find . -mtime -n n天以内修改的文件

find . -mtime +n n天以外修改的文件

find . -mtime n 正好n天修改的文件

-mmin 效果同上,不过单位是分钟。

-mindepth n 查找n目录层级

查找2级子目录下的普通的文件。

find . -mindepth 2 -type f

当多参数时mindepth必须要在第一个位置

-maxdepth n 表示最多搜索到n-1级子目录,不会遍历全部目录。

了解选项:

-nouser 搜索没有属主的

-nogroup 搜索没有属组的

-perm 655 搜索指定权限的

-prune 排除文件

搜索文件时排除test_1目录

find . -path ./test_1 -prune -o -type f

排除多个目录

find . -path ./test_1 -prune -o -path ./test_2 -prune -o -type f

-prune语法较为怪异。

-newer Afile 查找比Afile新的文件

文件操作

-print 将查询结果显示,默认开启。

-exec 对结果执行命令:

find . -name '*.bak' -exec cp {} /tmp/ ;

{}代表搜索到的结果, ;为特定格式。

-ok-exec功能相同但每次操作会给用户提示

逻辑运算符

-a 与 搜索条件之间的默认使用的运算符

-o

-not !


whereis

查命令二进制文件,命令man文档,命令源码。

参数:

-b 只返回二进制文件

-m 只返回帮助文件

-s 只返回源码文件(无则不返回)

无参数使用时默认使用全部参数。

which

将一个默认参数-b只返回唯一二进制文件。

Prev
2025-09-23 09:51:51
Next