linux+正则匹配日志,Linux下的awk、sed命令及正则表达式

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

Linux提供了awk和sed两个强大的命令行文本处理工具,在对大型日志文件分析时特别有用。对文本的处理结合正则表达式可以高效的获取自己想要的日志信息。本文只是对awk、sed和正则表达式在笔者使用过程中遇到的一些比较常用的功能进行记录,更详细的使用方法可以去相应的官方网站查看。

1 awk简单介绍

根据维基百科的介绍:AWK是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言的最大功能取决于一个人所拥有的知识。AWK提供了极其强大的功能:可以进行正则表达式的匹配,样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。

几乎所有的Linux都自带awk命令。它依次处理文件的每一行,并读取里面的每一个字段。对于日志文件那样的每行格式相同的文本文件,awk可能是最方便的工具。

1.1 基本用法

基本语法命令如下:1

2

3

4

5# 格式

$ awk actions fileName

# 示例

$ awk '{print $0}' test.log

上面的代码中,test.log就是要处理的文本文件。actions即动作,写在一对单引号内,引号内的命令一般需要一对大括号括起来。print是打印命令。

根据以上的基础语法,我们进行一次实践。1

2

3

4

5

6

7

8

9这里顺便学习echo命令如何输出单引号,目前了解到的方式是通过双引号把单引号引起来,然后将单引号两侧的字符串通过单引号引起来,放在一起即可。

$echo 'I'"'"'m learning awk' | awk '{print $0}'

I'm learning awk

$echo 'I'"'"'m learning awk' | awk '{print $1}'

I'm

$echo 'I'"'"'m learning awk' | awk '{print $2}'

learning

以上,我们可以看到,$0代表的是整行,$1默认为第一列,$2、$3以此类推。默认的分隔符是空格或制表符,即t的转义字符。

为便于加深理解,我们以/etc/passwd文件(该文件是通过冒号分开的有规律的文件)为例,进行如下操作:1

2

3

4

5

6

7

8

9$cat /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

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

root

bin

daemon

我们通过-F指定行的分隔符,然后输出每行的第一列。

1.2 内置变量

内置变量我们可以通过man awk命令,在结果中搜索Built-in Variables可以查询到所有的内置变量,这里对一些常用的做简单学习。变量名man手册解释个人理解NFThe number of fields in the current input record.当前行通过分隔符切割后一共有多少个字段。$NF就代表最后一个字段,相应的$(NF-1)就是倒数第二个字段。

NRThe total number of input records seen so far.表示当前处理的是第几行。

FILENAMEThe name of the current input file. If no files are specified on the command line, the value of FILENAME is “-”. However, FILENAME is undefined inside the BEGIN block (unless set by getline).当前处理的文件的文件名。

FSThe input field separator, a space by default.字段分隔符,默认是空格和制表符。

RSThe input record separator, by default a newline.行的分隔符,默认是换行符。

根据以上的内置变量,对其中的部分进行实践。1

2

3

4

5

6

7

8

9

10

11输出第一列和倒数第二列,中间用字符-隔开,双引号中的字符原样输出,如果是逗号,默认为空格

$cat /etc/passwd | awk -F':' '{print $1"-"$(NF-1)}'

root-/root

bin-/bin

daemon-/sbin

同上,输出行号

$cat /etc/passwd | awk -F':' '{print NR ")", $1, $(NF-1)}'

1) root /root

2) bin /bin

3) daemon /sbin

1.3 常用操作

准备文件awk.txt,文件内容如下:1

2

3

4

5

6

71 12

2 32

2 32

5 12

5 12

6 165

6 165

我们分别对其进行求和和去重操作。

1.3.1 求和

我们对第二列的值进行求和操作:1

2

3

4

5

6

7

8

9

10$awk 'BEGIN {sum = 0} {sum += $2} END {print sum}' awk.txt

430

同样的,可以进行求平均值操作,除以总行数即可

$awk 'BEGIN {sum = 0} {sum += $2} END {print sum/NR}' awk.txt

61.4286

格式化输出,同C语言的格式化输出

$awk 'BEGIN {sum = 0} {sum += $2} END {printf("%.2fn"), sum/NR}' awk.txt

61.43

1.3.2 去重

去重有两种方案可以实现。1

2

3

4

5

6

7

8

9

10

11

12

13#先使用sort进行排序,然后进行uniq操作

$sort awk.txt | uniq

1 12

2 32

5 12

6 165

#使用awk

$awk '!a[$0]++' awk.txt

1 12

2 32

5 12

6 165

关于!a[$0]++的个人理解:awk数组的下标可以为字符串(经证实,可以。如果不可以,a[$0]也可以理解为下标=hash($0))和数字。

如果action为空,默认action={print $0},上面的去重命令行等价于awk '!a[$0]++ {print $0}' awk.txt。

++操作是先使用值,然后自增。

由以上三点,可以得出以下执行逻辑:读取a[$0]的值,默认为0,进行非操作!a[$0]得到值为1,所以输出$0然后值自增为1,下一次执行的时候,如果a[$0] != 0,进行非操作,得到0,则该行不输出。

1.3.2 条件筛选

如果我们切割出来的列,包含了一些杂质,比如,本来该列均为数字,结果文件内容该位置出现的字母,那么,我们可以进一步进行条件筛选。以如下文本为例:1

2

3

4

5

6

7

81 12

2 32

2 32

5 12

5 12

6 165

6 165

h hello

我们的需求是筛选出第二列的所有数字,实现方式如下:1

2

3

4

5

6

7

8

9

10$awk '{tmp = $2} {if (tmp ~ /[0-9]+/) {print $2}}' awk.txt

#或者如下

$awk '/[0-9]+/ {print}' awk.txt

1 12

2 32

2 32

5 12

5 12

6 165

6 165

~是awk中的正则表达式的匹配,相应的还有!~操作符。关于正则表达式,后面会花时间进行初步学习。

2 sed实践

对sed不着过多笔墨,这里只对实际场景中用到的进行简单记录。更深层次的学习后续用到的时候在这里继续补充。目前sed在实战中的使用场景是,在shell启动脚本中,读取配置文件的参数,然后通过命令启动应用。有如下配置文件key=value格式,我们需要通过key读取到value。

配置文件sed.txt1

2

3server.name=api-service

server.port=8080

server.path=/test

我们需要分别读到服务名称、端口等信息,具体操作如下:1

2

3

4

5

6

7

8

9#读取服务名称

$sed '/server.name/!d;s/.*=//' sed.txt | tr -d 'r'

api-service

#读取启动端口

$sed '/server.port/!d;s/.*=//' sed.txt | tr -d 'r'

8080

#依次类推

对如上命令的理解和解释,在命令中以分号为界,分为两个部分:第一部分:/server.name/!d

/server.name/是一个正则表达式,表示包含字符串server.name的行,d是sed的一个删除命令操作,!d就是删除的反向操作,即删除所有不包含server.name字符串的行。执行sed '/server.name/!d' sed.txt可以得到server.name=api-service。

第二部分:s/.*=//

s在sed命令中的的含义为替换,后接的/.*=/是一个正则表达式,匹配的字符串为任何以=结尾的字符串,显然,这里匹配到的是server.name=。后面再接一个/,两个/之间的字符串为空,即将匹配到的字符串置为空,那么得到的结果就是api-service。

tr命令不在该文讨论范畴,可以自行查阅相关资料。这里的tr -d 'r'意思是删除末尾的换行符。

3 正则表达式

该文已经较长,接下来单独开一篇学习正则表达式。

以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux命令正则表达式是一种强大的工具,用于在文本进行模式匹配和搜索。正则表达式可以应用于各种命令(如grep、sedawk等),以及编辑器(如vim)和服务器(如nginx)等。正则表达式由字母、数字和特殊符号组成,按照一定的规则来表达某种含义。 在Linux命令,常见的正则表达式符号包括: 1. . (点号):匹配任意一个字符。 2. * (星号):匹配前一个字符的零个或多个出现。 3. + (加号):匹配前一个字符的一次或多次出现。 4. ? (问号):匹配前一个字符的零次或一次出现。 5. [] (方括号):用于定义字符集,匹配方括号任意一个字符。 6. ^ (脱字符):匹配行的开始位置。 7. $ (美元符号):匹配行的结束位置。 8. \ (反斜杠):用于转义特殊字符。 举个例子,如果你想在一个文件查找所有以"hello"开头的行,你可以使用grep命令结合正则表达式进行匹配。命令如下: grep "^hello" filename 其,^表示行的开始位置,"hello"表示要匹配的字符串。这个命令会输出所有以"hello"开头的行。 另外,正则表达式还支持更复杂的模式匹配,比如通配符、字符类、重复选项等。你可以根据具体的需求,结合正则表达式的语法规则,来构建适合你的匹配模式。 综上所述,正则表达式Linux命令是一个非常有用的工具,可以帮助你快速准确地进行文本搜索和模式匹配。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值