linux 三剑客

grep

指定的输入文件中搜索包含与给定模式匹配的行。一般用来搜索文件中的指定内容,和搜索包含指定内容的文件。

命令格式

grep [option...] [patterns] [file...]

一般模式需要用引号括起来。

常用选项

选项含义
-i忽略大小写
-c只输出匹配行的数量
-n显示行号
-r递归搜索
-E支持拓展正则表达式
-w匹配整个单词
-l只列出匹配的文件名
-F不支持正则,按字符串字面意思进行匹配

举例:
现在有文件file.txt,内容如下

#test.txt
abc
ABC
bcd
acea
helloworld
^b

搜索包含a内容的行

grep a test.txt
结果:
abc
acea

搜索以a结尾的内容

grep "a$" test.txt
结果:
acea

-i 忽略大小写

grep -i "a" test.txt
结果:
abc
ABC
acea

-c 只输出匹配行的数量

grep -c "a" test.txt
结果:
2
grep -c "" test.txt
结果:
6

-n 显示行号

grep -n "a" test.txt
结果:
1:abc
4:acea

-r 递归搜索,当递归地读取和处理目录中的所有文件时需要加上-r, 在当前目录复制一个test1.txt文件,通过递归搜索包含hello的文件

grep -r hello .
结果:
./test1.txt:helloworld
./test.txt:helloworld

-l 只列出匹配的文件名

grep -lr 'a' . 
结果:
./test1.txt
./test.txt

-w 匹配整个单词

# 不加-w时会匹配到hello
grep  hello test.txt
结果:
helloworld
#全词匹配 -w
grep  -w hello test.txt
结果为空

-F 不支持正则,当匹配的内容为正则表达式的符号时,需要加-F来表示字符串字面意思进行匹配

# 查找^b字符,不加-F,默认会以正则字符去匹配,查找以b开头的内容
grep ^b test.txt 
结果:
bcd
# 加上-F
grep -F ^b test.txt 
结果:
^b

-E 支持拓展正则表达式,当使用正则表达式匹配时需要加-E

grep -E '(bc)' test.txt 
结果:
abc
bcd

sed

sed(stream editor)流编辑器,对文件逐行处理。通常用来过滤,替换,修改文本。

命令格式

sed OPTIONS... [SCRIPT] [INPUTFILE...]

常用选项 OPTIONS

选项含义
-n-n抑制默认的每行输出,一般会和p命令一起使用
-f加载存放动作的文件
-r支持拓展正则
-i直接修改文件

sed命令

这里的sed命令就是上面的[SCRIPT]部分。

语法

[addr]X[options]
#X是单字母sed命令

[addr]是可选行地址,如果指定了[addr],命令X将只在匹配的行上执行。
[options]是某些sed命令的额外选项

常用命令

命令说明
p打印处理后的内容
a text在匹配行后插入指定内容,注意a后面有个空格
i text在匹配行前新增指定内容,注意i后面有个空格
r filename读取文件filename的内容,然后插入匹配行后
wfilename 将匹配内容写入文件filename中
d删除匹配的行
s/regexp/replacement/[flags]将匹配的行中匹配regexp的部分替换为replacement,flags:g全替换,i忽略大小写,m匹配多行

地址选择

表达式说明
number匹配第number行
$匹配最后一行
first~step匹配从first开始的每step行,例如1~ 2表示选择奇数行,0~2表示选择偶数行
m,n匹配从第m到第n行
/regexp/匹配能匹配regexp的行

继续以上面的文本内容为例:

#test.txt
abc
ABC
bcd
acea
helloworld
^b

-n抑制默认的每行输出,一般会和p命令一起使用打印奇数行内容

sed -n '1~2p' test.txt # 如果不加-n,那么sed会每出来一行就会输出一次。
结果:
abc
bcd
helloworld

s/regexp/replacement/[flags] 替换,flags默认为g全部替换,i忽略大小写,m匹配多行

# 将test.txt中的abc替换成cba
sed 's/abc/cba/' test.txt 
结果:
cba
ABC
bcd
acea
helloworld
^b
# 加i忽略大小写
sed 's/abc/cba/i' test.txt 
结果:
cba
cba
bcd
acea
helloworld
^b

此时test.txt文件内容时没有被修改的,只是在读取后进行了替换并输出。如果想修改文件内容需要加-i。

-i 直接修改文件

sed -i 's/abc/cba/i' test.txt 
# 保险起见,修改的同时备份一份源文件,可以在i后面加后缀名
sed -ibak 's/abc/cba/i' test.txt 

a text 在匹配行后插入指定内容,注意a后面有个空格
i text 在匹配行前新增指定内容,注意i后面有个空格

 sed 'a ccc' test.txt   # 在每一行的后面插入abc
 sed '1a ccc' test.txt   # 在第一行的后面插入abc
 sed '/^B/a abc' test.txt  # 在以B开头的行后面插入abc
 sed '/^B/i abc' test.txt  # 在以B开头的行前面插入abc

r filename 读取文件filename的内容,然后插入匹配行后
举例:
有文件text.txt,text1.txt内容如下

# test.txt
hello
world

#text1.txt
a
b
c
# 将test.txt中的内容插入到test1.txt的第1行后面
sed '1 r test.txt' test1.txt

结果:
a
hello
world
b
c

w filename 将匹配内容写入文件filename中
继续以上面的文件内容为例:

#将test.txt中的第一行内容写到test1.txt中
sed '1w test1' test1.txt

d 删除匹配的行

#删除test.txt的第一行
sed '1d' test.txt
# 如果真正删除源文件内容加-i即可
sed -i '1d' test.txt

通过N参数合并行
举例:
test.txt文件内容如下

hi!
hello
world

将hello world合并成1行

sed '2{N;s/\n//;}' test.txt
# 在第二行先把换行替换为空然后再通过N参数把下一行合并进来
hi!
helloworld

awk

awk是一种解释型编程语言,类似于python。一般用于对数据文件的处理。

命令格式

awk 'BEGIN{commands}pattern{commands}END{commands}' file;
格式说明
BEGIN{}处理数据之前执行
pattern匹配模式
{commands}处理的命令,必须使用大括号包含
END{}处理数据之后执行

匹配模式
匹配模式用来筛选要处理的数据。awk中的模式有如下几种:

正则表达式
要使用斜杠包裹起来:/regexp/

普通表达式
一般是一个比较表达式

image20220115161705073

例如:

$1 == "on"		# 第一个字段等于on
BEGIN END
为awk程序提供启动或清理操作的特殊模式。

BEGIN在处理前执行

END在处理后执行

内置变量

内置变量含义
$0整行内容
$ 1,$n当前行的第1至n个字段
NF(Number Field) 当前行字段数,$NF就是最后一个字段
NR(Number Row) 当前行行号,从1开始
FS(Field Separator) 输入字段分割符,默认为空格或tab键
RS(Row Separator) 输入行分割符,默认为回车符
OFS(Output Field Separator) 输出字段分割符,默认为空格
ORS(Output Row Separator) 输出行分割符,默认为回车符

输出命令

print item1, item2, ...
打印item1,item2,用空格连接,如果省略了逗号,中间的空格会被省略

printf format, item1,time2,...
格式化输出,c语言风格。

举例
有1.txt文件内容如下:

a 1-1 22
b 3-3 44
c 5-5 66
d 7-7 88

1.$n筛选当前行的第一个字段:

awk '{print $1}' 1.txt # 默认为空格或tab键分割,$2就是每行的第2个字段,以此类推
结果:
a
b
c
d

2.$ 1,$n筛选当前行的第1到2个字段

awk '{print $1,$2}' 1.txt 
结果:
a 1-1
b 3-3
c 5-5
d 7-7

3.NF(Number Field) 当前行字段数

awk '{print NF}' 1.txt
结果:
3
3
3
3
# 获取最后一行可以通过$NF
awk '{print $NF}' 1.txt
结果:
22
44
66
88

4.NR,行号

awk '{print NR}' 1.txt
结果:
1
2
3
4

5.FS(Row Separator) 指定字段分割符默认为空格或tab键
当有些文件内容并不是以空格或tab键分割时,在处理数据之前可以通过FS指定分割符。
如下以-号分割输出1.txt文件内容的第一个字段

awk 'BEGIN{FS="-"} {print $1}' 1.txt
结果:
a 1
b 3
c 5
d 7

6.RS(Row Separator) 指定行分割符,默认为回车符
修改1.txt内容如下

a 1-1 22t3
b 3-3 44t4
c 5-5 66t5
d 7-7 88t6
# 通过RS指定以t为换行符,输出全部行
awk 'BEGIN{RS="t"} {print $0}' 1.txt
结果:
a 1-1 22
3
b 3-3 44
4
c 5-5 66
5
d 7-7 88
6

7.OFS(Output Field Separator) 输出字段分割符,默认为空格
如下输出第一个第二个字段以~符链接

awk 'BEGIN{OFS="~"}{print $1,$2}' 1.txt 
结果:
a~1-1
b~3-3
c~5-5
d~7-7
// An highlighted block
var foo = 'bar';
// An highlighted block
var foo = 'bar';

简单案例

数据内容
文件mail-list包含如下内容:

Amelia       555-5553     amelia.zodiacusque@gmail.com    F
Anthony      555-3412     anthony.asserturo@hotmail.com   A
Becky        555-7685     becky.algebrarum@gmail.com      A
Bill         555-1675     bill.drowning@hotmail.com       A
Broderick    555-0542     broderick.aliquotiens@yahoo.com R
Camilla      555-2912     camilla.infusarum@skynet.be     R
Fabius       555-1234     fabius.undevicesimus@ucb.edu    F
Julie        555-6699     julie.perscrutabor@skeeve.com   F
Martin       555-6480     martin.codicibus@hotmail.com    A
Samuel       555-3430     samuel.lanceolis@shu.edu        A
Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
这是一个邮箱列表,每条记录包含姓名,电话号码,邮箱地址以及一个表示关系的字母,F表示朋友,A表示认识的人,R表示亲戚。

文件inventory-shipped包含如下内容:

Jan  13  25  15 115
Feb  15  32  24 226
Mar  15  24  34 228
Apr  31  52  63 420
May  16  34  29 208
Jun  31  42  75 492
Jul  24  34  67 436
Aug  15  34  47 316
Sep  13  55  37 277
Oct  29  54  68 525
Nov  20  87  82 577
Dec  17  35  61 401

Jan  21  36  64 620
Feb  26  58  80 652
Mar  24  75  70 495
Apr  21  70  74 514
#这是一个发货清单,每条记录包含月份,以及A,B,C,D四种商品的发货数量。这里有16条记录,包含去年12月以及今年4个月的发货记录。使用一个空行分隔两年的数据。

1.筛选记录中包含li的邮件联系人

awk '/li/ { print $0 }' mail-list  # { print $0 }可以省略,模式就是这个action

2.筛选字符数大于8的记录

awk 'length($0) > 8' mail-list  

3.最长记录的字符数

awk '{ if (length($0) > max) max = length($0) } END { print max }' mail-list  # 通过变量max记录,最后再END语句中输出

4.打印至少包含一个字段的行

awk 'NF > 0' data

5.打印7个0-100之间的随机数

awk 'BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }'

6.打印文件文件夹的总字节数

ls -l . | awk '{ x += $5 } END { print "total bytes: " x }'

7.打印文件文件夹的总KB数

ls -l files | awk '{ x += $5 } END { print "total K-bytes:", x / 1024 }'

8.打印所有用户登录名的排序列表

awk -F: '{ print $1 }' /etc/passwd | sort

9.计算文件中的行数

awk 'END { print NR }' data

10.打印数据文件中的偶数行

awk 'NR % 2 == 0' data

11.打印第一个字段和最后一个字段

awk '/li/ { print $1, $NF }' mail-list

12.格式化输出第一第二个字段

awk '{ printf "%-10s %s\n", $1, $2 }' mail-list

13.统计今年和去年的A商品的发货总数

#思路,在碰到换行符之前使用lastyear累加,碰到换行符之后使用currentyear累加

awk 'BEGIN{ l=1 }{ if(l==1) lastyear+=$2; else currentyear+=$2 } { if(NF==0) l=0} END{ printf "lastyear: %s, currentyear: %s\n", lastyear, currentyear }' inventory-shipped

14.统计去年A商品的月发货平均数

awk 'BEGIN{ l=1 } { if(l==1) lastyear+=$2 } {if (NF==0) l=0 } END{ printf "lastyear A average:%.2f\n", lastyear / 12 }' inventory-shipped

15.指定分隔符

awk 'BEGIN{ FS="-" } {print $1}' mail-list
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久醉绕心弦,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值