hello云胜

技术与生活

0%

正则表达式

正则表达式

基础

语法汇总:

^word 以word为行首的那一行
word$ 以word为行尾的那一行
. 代表一个任意字符
* 代表前面的字符重复0次或多次,注意可以是0次
\ 转义
[多个字符] 代表多个字符中的一个,或的关系
[a-z] -代表返回,比如a-z表示全部小写字母,A-Z代表所有大写字母。
[^字符] 取反,不包含这个字符。注意^在[]里和[]外的不同含义
\{n,m\} {}里加次数,表示重复指定次数。\{n,m\}是重复n到m次。\{n,\}是重复n次以上

另外,注意区分正则表达式和通配符的区别。强调*这个字符

在正则中表示重复前面的字符0次或多次

在通配符中表示任意字符

举例来说。(ls命令是不支持正则的,grep,sed支持)

1
ls -l a*

是取出以a开头的所有文件

1
grep 'a*' 某文件

会把文件中所有的数据全部取出,因为正则中*可以表示0次,所以a*的含义就是所有字符,而不是以a开头的意思

正则表达式延申

上面是正则的基本语法,除此之外,正则还有延申的特殊参数

要使用的话用grep -E,不过更常用的是egrep

+ 代表前面的字符重复1次或多次,注意和*的区别
0次或1次
| 或的含义
() 分组
()+ 多个重复分组

sed

sed当管道使用

sed是一个管道命令。

sed后接动作要用单引号括住

1
sed '2,5d'

2,5表示对第二行到第五行进行动作。d表示删除动作

可以接的动作如下

  • d删除。前面加上行号。如上所示,如果要实现从某一行删除到文件结束sed '2,$d'

  • a 新增。后面加上内容。在当前行的下一行新增内容

    1
    2
    3
    4
    5
    [api@kfxqtyglpt ~]$ cat test.txt
    456
    [api@kfxqtyglpt ~]$ cat test.txt | sed '1a okokok'
    456
    okokok

    sed也是管道操作,所以直接输出到了控制台上

  • i在前面新增。接的内容插入在上一行

    1
    2
    3
    [api@kfxqtyglpt ~]$ cat test.txt | sed '1i helphelp'
    helphelp
    456
  • p 显示

    我们要显示一个文件的第10到20行,可以用

    1
    head -n 20 | tail -n 10

    现在有了sed,可以直接

    1
    sed -n '10,20p'
  • s 搜索并替换,这是sed很常用的功能

    1
    sed 's/old/new/g'

    old部分可以用正则表达式

  • c按行取代

    1
    2
    3
    4
    5
    6
    [api@kfxqtyglpt ~]$ cat test.txt
    456
    the last line
    [api@kfxqtyglpt ~]$ cat test.txt | sed '1c the first line'
    the first line
    the last line

sed直接修改文件

比较危险,使用时先用管道场景进行测试

1
sed -i '$a the last line' test.txt

加上-i参数就是直接修改文件,为不是输出到console了

$是最后一行,$a就是在最后以后后新增的意思了

awk

将一行数据分成多个段来处理

格式

1
awk '条件1{动作1} 条件2{动作2}...' 文件名

awk的处理流程是:

  1. 将文件第一行读入,并赋给变量$0,$1,$2…,awk默认的分割符是空格或tab
  2. 根据条件判断,执行动作
  3. 执行完所有动作
  4. 继续下一行

变量$0是一整行的数据,$1是第一分段数据

awk的内建变量:

NF:每一行($0)拥有的分段总数

NR:当前awk是在处理第几行

FS:当前的分隔符

自定义分隔符

通过FS=”:”可以设置分隔符为:

1
2
3
4
5
6
$ last -n 5 |egrep -v '^$|wtmp' | awk '{FS=":"} {print $1 "\t all:" NF "\t now: " NR}'
api all:10 now: 1
api pts/12 1x.xx.0.66 Fri Feb 3 11 all:4 now: 2
root pts/4 1x.xxx.7.21 Fri Feb 3 11 all:4 now: 3
api pts/1 1x.xx.179.212 Fri Feb 3 11 all:4 now: 4
api pts/4 1x.xx.179.212 Fri Feb 3 10 all:4 now: 5

但是这样有个问题,就是第一行在执行的时候,分隔符还是空格,所以第一行的结果有问题

解决办法是使用关键字BEGIN

1
2
3
4
5
6
[api@kfxqtyglpt ~]$ last -n 5 |egrep -v '^$|wtmp' | awk 'BEGIN {FS=":"} {print $1 "\t all:" NF "\t now: " NR}'
api pts/1 1x.xx.179.212 Fri Feb 3 14 all:2 now: 1
api pts/12 1x.xx.0.66 Fri Feb 3 11 all:4 now: 2
root pts/4 1x.xxx.7.21 Fri Feb 3 11 all:4 now: 3
api pts/1 1x.xx.179.212 Fri Feb 3 11 all:4 now: 4
api pts/4 1x.xx.179.212 Fri Feb 3 10 all:4 now: 5

条件

awk中可以使用条件运算符:>,<,>=,<=,==,!=

1
2
3
4
5
6
[api@kfxqtyglpt ~]$ last -n 5 |egrep -v '^$|wtmp' | awk 'BEGIN {FS=":"} {printf $1 "\t all:" NF "\t now: " NR} NR>3 {printf "\t more than 3 \n"} NR<=3 {printf "\n"}'
api pts/4 1x.xx.181.65 Fri Feb 3 14 all:2 now: 1
api pts/1 1x.xx.179.212 Fri Feb 3 14 all:2 now: 2
api pts/12 1x.xx.0.66 Fri Feb 3 11 all:4 now: 3
root pts/4 1x.xxx.7.21 Fri Feb 3 11 all:4 now: 4 more than 3
api pts/1 1x.xx.179.212 Fri Feb 3 11 all:4 now: 5 more than 3

对大于3的行添加了一个输出。注意我这里使用了printf,要自己加上\n换行