ThankNeko's Blog ThankNeko's Blog
首页
  • 操作系统

    • Linux基础
    • Linux服务
    • WindowsServer笔记
    • Ansible笔记
    • Shell笔记
  • 容器服务

    • Docker笔记
    • Kubernetes笔记
    • Git笔记
  • 数据库服务

    • MySQL笔记
    • ELK笔记
    • Redis笔记
  • 监控服务

    • Zabbix笔记
  • Web服务

    • Nginx笔记
    • Tomcat笔记
  • 数据处理

    • Kettle笔记
  • Python笔记
  • Bootstrap笔记
  • C笔记
  • C++笔记
  • Arduino笔记
  • 分类
  • 标签
  • 归档
  • 随笔
  • 关于
GitHub (opens new window)

Hoshinozora

尽人事,听天命。
首页
  • 操作系统

    • Linux基础
    • Linux服务
    • WindowsServer笔记
    • Ansible笔记
    • Shell笔记
  • 容器服务

    • Docker笔记
    • Kubernetes笔记
    • Git笔记
  • 数据库服务

    • MySQL笔记
    • ELK笔记
    • Redis笔记
  • 监控服务

    • Zabbix笔记
  • Web服务

    • Nginx笔记
    • Tomcat笔记
  • 数据处理

    • Kettle笔记
  • Python笔记
  • Bootstrap笔记
  • C笔记
  • C++笔记
  • Arduino笔记
  • 分类
  • 标签
  • 归档
  • 随笔
  • 关于
GitHub (opens new window)
  • 操作系统

    • Linux基础

      • 服务器与Linux介绍
      • VMware虚拟机安装
      • 查看系统信息
      • 开机挂载与自启
      • 系统运行级别
      • 变量与命令别名
      • 网卡配置
      • 文件系统inode与block详解
      • 系统优化
      • 文件管理
      • 用户管理
      • 文本处理三剑客
        • Linux符号
        • grep命令
        • sed命令
        • awk命令
      • 定时任务
      • 磁盘分区
      • 其他基础命令
    • Linux服务

    • Windows Server笔记

    • Shell笔记

    • Ansible笔记

  • 虚拟化服务

  • 数据库服务

  • 监控服务

  • Web服务

  • 数据处理

  • Ops
  • 操作系统
  • Linux基础
Hoshinozora
2023-02-28
目录

文本处理三剑客

# Linux符号

Linux中存在一些特殊符号用于实现特定的功能。

# 通配符号

通配符号*用于根据文件名称进行匹配。

例如:

# 查看名称以.txt结尾的文件信息。
ls -l *.txt
1
2

# 引号符号

# '':将单引号内的信息全部转义为普通字符。
echo '$UID'
> $UID

# "":将双引号内的信息,特殊信息进行解析。
echo "Root UID: $UID"
> Root UID: 0

# ``或$():将引号中的命令先执行,将执行结果交给引号外面的命令。
echo "I am `echo 123`"
> I am 123

# $()还可以用来整数运算
echo $((1+1))

# 没有引号:和双引号功能类似,不同在于可以直接通配符信息、且有空格可能会被当成两部分。
echo 123
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 转义符号

\是转义符号。

用于将有特殊意义符号转义为普通信息进行识别。

# \$会将$转义为普通字符"$"
echo "I am \$"
> I am $
1
2
3

或则将没有意义的信息转义为有特殊意义的信息。

\t 制表。

\n 换行。

\ 也可转义空格。

# 逻辑符号

逻辑符号可以用在命令执行中,用于实现更复杂的命令逻辑。

# &&:与/并且,前一个命令执行成功后面的命令才会执行。
# 例如:只有test.txt存在时,才会写入123到test.txt
touch ./test.txt && echo "123" > ./test.txt

# ||:或/或者,前一个命令执行失败,后面的命令才会执行。
# 例如:只有test.txt不存在时,才会创建test.txt
ls ./test.txt || touch ./test.txt
1
2
3
4
5
6
7

# 正则符号

正则符号用于根据符号进行内容匹配。

基础正则符号:

^ 尖号符号,匹配开头。

$ 美元符号,匹配结尾。

. 点字符,代表任意一个字符。

* 星字符,匹配前一个字符至少出现零次或多次连续的信息。

[] 中括号,匹配括号中所有字符的任意一个字符信息。

  • [x-y] 匹配范围内的任何字符。
  • [^] 不匹配[]内的任何字符。

扩展正则符号:

+ 加号,匹配前一个字符至少出现一次或多次连续的信息。

| 或符号,用于匹配多个信息。

? 问号,匹配前一个字符出现零次或一次的信息。

() 小括号,非捕获分组,而是使信息作为整体进行匹配。

需要以此格式:(?:xxx|xxx|xxx...)

{} 花括号,可以指定前一个字符连续匹配的次数。

x{n,m} 指定前一个字符连续匹配的最小次数和最大次数。

x{n,} 指定前一个字符连续匹配的最小次数。

x{,m} 指定前一个字符连续匹配的最大次数。

x{n} 指定前一个字符正好连续匹配的次数。

其他正则符号:

~ 匹配包含,判断某内容是否包含某内容,包含则匹配。

  • 如"test1231" ~ /te/是匹配成功的。

!~ 匹配不包含。

注意:

默认grep、sed命令不能直接识别扩展正则。

grep使用扩展正则需要加上-E参数,或直接使用egrep命令。

sed使用扩展正则需要加上-r参数。

# grep命令

grep命令主要用于筛选文件内容,过滤出想要找出的信息,常用于查找日志等场景。

# 命令语法

grep 参数 "正则表达式" 文件

-c 统计匹配的信息个数。

-v 显示不匹配的内容,即取反和排除。

-E 使支持扩展正则,或直接使用egrep命令。

-o 显示匹配过程。

-B n 显示匹配内容行和上面n行。

-A n 显示匹配内容行和下面n行。

-C n 或 -n 显示匹配内容行和上下n行。

-i 忽略大小写筛选。

# 例子

#筛选以test开头的行。
grep "^test" ./test

# 筛选以test结尾的行。
grep "test$" ./test

# 排除空行,-v表示排除。
grep -v "^$" ./test

# 以指定信息开头和结尾,此处为匹配a开头和b结尾的行
grep "^a.*b$" ./test

# 指定具体信息进行贪婪匹配,找到P开头后匹配到最后一个me停下。
grep "^P.*me" ./test

# 指定具体信息进行非贪婪匹配,找到P开头后匹配到第一个me停下。
grep "^P.*me" ./test

# 匹配不同字符开头的信息,匹配P或h开头的信息。
grep "^[Ph]" ./test

# 匹配所有以英文字符开头的信息。
grep "^[a-Z]" ./test

# 排除有指定字符的信息,排除包含a/b/c的信息。
grep "[^abc]" ./test

# 排除包含指定字符开头的信息,排除a/b/c开头的信息。
grep "^[^abc]" ./test

# 匹配所有数字字符,[0-9]+表示匹配一个或连续的数字,也就是匹配所有数字。
grep "[0-9]+" ./test

# 匹配多个信息,同时匹配one和two。
grep -r "one|two" ./test

# 筛选IP
ip a s eth0 | grep "inet " | egrep "([0-9]{1,3}\.?){4}" -o
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
26
27
28
29
30
31
32
33
34
35
36
37
38

# sed命令

# 命令介绍

sed命令是一个字符流编辑工具(行编辑工具),擅长对行进行修改,它会按照每行中的字符进行处理操作,对文件内容具有增删改查的能力。

# 执行过程

  1. sed命令先将一行内容读取到内存中(模式空间)。
  2. 因为默认是在内存中处理,所以如果要实际修改文件需要加-i参数。
  3. 然后判断这一行是否满足条件,如果满足条件则处理后再读取下一行,不满足则直接读取下一行。
  4. sed默认会输出读取的内容到屏幕,可用-n参数取消默认输出。

# 命令语法

sed 参数 '条件/处理指令' 文件

参数:

-n 取消默认输出,只输出处理的内容。

-r 识别扩展正则。

-i 真实写入文件(将内存中的信息覆盖到磁盘中)。

-i.bak 修改时自动备份,-i后面应当只有备份后缀,参数应当放前面。

-e 识别sed命令的多个操作指令。

指令:

p:输出内容(print)。

! 取反。

!p:输出取反的匹配内容

s:替换内容(substitute),例如:s#[欲替换内容]#[目标内容]#g 其中g代表全局替换。

i:插入内容(insert),在指定内容前面插入新内容。

a:追加内容(append),在指定内容后面插入新内容。

注意事项:

修改文件内容时,不要同时使用n和i参数,会将文件内容全部变成输出的内容。

# 使用例子

添加内容(增)

# 在指定行上面添加内容
sed -i '1i test' ./test

# 在指定行下面添加内容
sed -i '1a test' ./test

# 在最后一行添加内容
sed -i '$a test1\ntest2' ./test

# 在有匹配内容所在行的上下添加内容
sed -e '/test/i one' -e '/test/a two' ./test
1
2
3
4
5
6
7
8
9
10
11

删除内容(删)

# 删除指定行
sed -i '3d' test

# 删除连续多行
sed -i '1,3d' ./test

# 删除有指定内容的行
sed -i '/test/d' ./test

# 指定行号删除多行
sed -i '1d;3d' ./test

# 指定匹配内容删除多行
sed -i '/test1/d ; /test2/d' ./test

# 删除空行
sed -i '/^$/d' ./test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

修改内容(改)

# 如果内容有#可以使用/,或者使用反斜杠将内容中的#转义。
sed -i 's#原有内容#目标内容#g' ./test
sed -i 's/原有内容/目标内容/g' ./test

# 将指定行的整行内容进行替换
sed -i '2c lalalalala' ./test
1
2
3
4
5
6

查询内容(查)

# 输出指定行内容
sed -n '3p' ./test

# 输出指定连续多行内容
sed -n '1,3p' ./test

# 输出匹配内容的行
sed -n '/test/p' ./test

# 多个匹配条件进行输出
sed -n '/test1/p ; /test2/p' ./test

# 输出两个匹配内容及其之间的所有行。
sed -n '/test1/,/test2/p' ./test
1
2
3
4
5
6
7
8
9
10
11
12
13
14

实际案例

# 取出IP地址。
ip a show eth0 | sed -n '3p' | sed -r 's#.*net (.*) brd.*#\1#g'
# 或
ip a show eth0 | sed -rn '3s#.*net (.*) brd.*#\1#gp'

# 实际修改时进行备份。
sed -i.bak '3p' ./test

# 批量创建用户,()将前项内容交给后项处理。
# 1.先将echo输出的信息用xargs转化成多行。
# 2.然后用sed将每行内容替换成useradd + 每行内容,其中()代表整行内容,而\1代表引用第一个括号内的内容。
# 3.最后将替换好的内容交由bash解释器执行。
echo user{01..05} | xargs -n1 | sed -r "s#(.*)#useradd \1#g" | bash
# 或
seq -w 10 |sed -r "s#(.*)#useradd user\1#g" | bash

# 批量创建并改密码
echo test{06..10} | xargs -n1 | sed -r "s#(.*)#useradd \1 ; echo "123456" | passwd --stdin \1#g" | bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# awk命令

# 命令介绍

awk擅长对文件进行分析,模式扫描和处理文件语言,awk和grep没有和sed一样的直接对文件进行处理的方式,只是将处理结果输出到屏幕。

# 执行过程

  1. awk命令执行时,会先执行BEGIN{}内的动作。
  2. 然后将文件内容一行一行的读取覆盖到$0以换行符结束,并将内容以分隔符切割给$n。
  3. 如果有条件,则对满足条件的行进行处理执行动作,不满足直接读取下一行。
  4. 如果只有动作,没有匹配条件,则直接对该行执行动作,然后继续读取下一行。
  5. 全部处理完后执行END{}内的事情。

# 内置变量

NR 表示行号。

NF 表示每一行有多少列。

FS 字段分隔符变量,可以直接通过变量修改,也可以通过-F参数指定。

# 命令语法

awk [参数] '模式-动作' 文件

awk中调用变量不用加$, 如果普通字符被当成变量可以加上""将其包裹。

参数:

-v变量名="变量值" 设置变量。另外如果直接在动作中使用未定义的变量,默认会从0开始。

-F "[\t: ]+" 设置制表符为字段分隔符。

  • 同等于BEGIN{FS="[\t: ]+"}或-vFS="[\t: ]+"。

普通模式:

正则表达式作为模式:

'/内容/' 查找指定内容。

'$3~/内容/' 查找指定列含内容的信息。

$0!~ 取反。

比较匹配作为模式:

'NR==n' 匹配指定行。

'NR<n' 匹配行号小于n的行。

'NR>n' 匹配行号大于n的行。

'NR<=n' 匹配行号小于等于n的行。

'NR==n, NR==m' 匹配n和m行。

逻辑操作符进行匹配:

&& 并且,例如:NR>=n && NR<=m

|| 或者,例如:NR==n || NR==m

! 非。

特殊模式:

BEGIN{}:在读取文件前执行的动作,比如加上表头、运算、指定awk变量等。

awk 'BEGIN{print "a","b"}' ./test

awk 'BEGIN{print 1+1}' ./test

awk 'BEGIN{FS="[: ]+"}' ./test
1
2
3
4
5

END{}:在文件处理后执行的动作,比如提示、统计、计算等。

awk 'END{print "操作结束"}' ./test

awk '/^$/{i++}END{print i}' ./test
1
2
3

动作:

{}:表示使用动作,多个动作之间用;分隔。

, 表示空格,"," 表示使用,字符。

NF 表示倒数第一列。

$(NF-1) 表示倒数第二列。

$列数 表示第n列。

$0 表示整行所有列。

{i++} 算数运算。

print 输出。

gsub(/欲替换信息/,"目标信息",欲修改列) 全局替换。

if判断:

{ if (条件) {命令} } 单分支。

{ if (条件) {成立命令1} else{不成立命令2} } 双分支。

{ if (条件1) {成立命令1} else if (条件2) {命令2}... } 多分支。

for循环:

{ for (变量 in 迭代对象) {命令} }

{ for (初始变量;条件;自增减) {命令} } C语言风格。

while循环:

{ while (条件) {循环体} }

数组定义:

数组名[索引]=值,索引可以是数值,也可以是字符串。例如:test[1]=233。

如果值是字符串必须加双引号,例如:test[1]="hhh"。

支持自增自减赋值,默认从0开始,例如:test[1]++。

数组调用:

数组名[索引],例如:print test[1]。

作为迭代对象时不用加索引,例如:{for ( i in test ) print i }。

# 使用例子

# 按照行号查询指定行。
awk 'NR==2' ./test

# 按照行号查询指定连续行。
awk 'NR==2,NR==5' ./test

# 按照行号查询指定多行。
awk 'NR==2;NR=6' ./test

# 按照指定内容查询指定行。
awk '/test/' ./test

# 按照指定内容查询指定多行。
awk '/test1/;/test2/' ./test

# 输出匹配行的第一列和第二列。
awk 'NR==2{print $1 "," $3}' ./test

# 输出匹配行的倒数第二列。
awk -F "[: ]+" '/test/{print $(NF-1)}' ./test

# 查找第三列以41开头的行。
awk '$3~/^41/' ./test

# 查找第三列以1或5结尾的行。
awk '$3~/1$|5$/' ./test

# 将第一行的a替换为1。
awk 'NR==1{gsub(/a/,"1",$1);print}' ./test.txt

# 求和运算。
seq 10 | awk '{sum=sum+$n}; END{print sum}'

# 对文本空行进行计数
awk '/^$/{i++}; END{print i}' ./test

# 单分支判断。
awk -F: '{if ($3==0) {print $1} }' /etc/passwd

# 双分支判断。
awk -F: '{if ($3>0 && $3<1000) {print "虚拟用户"$1} else {print "可登录用户"$1} }' /etc/passwd

# 多分支判断。
awk -F: '{if ($3>0 && $3<1000) {print "虚拟用户"$1} else if($3==0) {print "超级用户"$1} else{print "普通用户"$1} }' /etc/passwd
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

# 实际案例

# 统计Nginx页面的PV量,即一个页面的浏览量,用户每刷新一次就有一个PV。

## 统计当天站点总PV量。
awk '$4~/04\/Apr\/2021/{i++} END{print "2021年4月4日PV量为"i}' access.log

## 统计当天站点12:00-16:00的PV量。
awk -F: '$1~/04\/Apr\/2021/ {if ($2 >=12 && $2 < 16) {i++} } END{print "2021年4月4日12-16点的总PV量为:"i}' access.log
awk '$4>="[04/Apr/2021:12:00:00" && $4<"[04/Apr/2021:16:00:00" {print $0}' access.log |wc -l

## 统计4月4日访问次数最多的前10个页面。
awk '$4~/04\/Apr\/2021/{pages[$7]++} END{for (i in pages) print pages[i]"\t"i}' access.log |sort -nr | head -10


# 统计Nginx日志中IP访问次数。

## 统计4月4日中访问次数最多的前十个IP。
awk '$4~/04\/Apr\/2021/{ips[$1]++}  END{for (i in ips){print ips[i]"\t"i}}' access.log | sort -nr | head -10

## 统计4月4日12-16点访问次数最多的前十个IP
awk -F '[ :]+' ' $4~/04\/Apr\/2021/ && $5>=12 && $5<16 {ips[$1]++}  END{for (i in ips){print ips[i]"\t"i}}' access.log | sort -nr | head -10

## 统计4月4日访问次数最多的时间段。
awk -F '[: ]+' '{print $5}' access.log  | sort | uniq -c | sort -nr

## 统计4月4日访问次数大于100的IP。
awk '$4~/04\/Apr\/2021/{ips[$1]++} END{for (i in ips) { if(ips[i]>100){print ips[i]"\t"i} } }' access.log


# 统计Nginx日志状态码。

## 统计4月4日状态码为404的次数。
awk '$4~/04\/Apr\/2021/ && $9~/404/ {i++} END{print i}' access.log

## 统计4月4日12点-16点 状态码为404的次数。
awk -F '[ :]+' '$4~/04\/Apr\/2021/ && $5 >=12 && $5 < 16 && $12~/404/ {i++} END{print i}' access.log
awk '$4 >="[04/Apr/2021:12:00:00"  && $4 < "[04/Apr/2021:16:00:00" && $9~/404/ {i++} END{print i}' access.log
awk '$9~/404/' access.log | egrep '04/Apr/2021:1[2-5]' | wc -l

## 统计4月4日每个IP所有状态码的次数
awk '{states[$1 "\t" $9]++} END{for (i in states) print states[i]"\t"i }' access.log |sort -k2

# 统计日志中每个URL的总大小
awk '{size[$7]+=$10} END{for (i in size)print int(size[i]/1024/1024)"MB\t"i }' access.log |sort -nr | head -10
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#Linux#文本处理#文本过滤#正则匹配
用户管理
定时任务

← 用户管理 定时任务→

最近更新
01
二〇二五年四月十七日随笔
04-17
02
二〇二五年四月十六日随笔
04-16
03
二〇二五年四月九日随笔
04-09
更多文章>
Theme by Vdoing | Copyright © 2022-2025 Hoshinozora | MIT License
湘ICP备2022022820号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式