续正则表达式与Linux文本三剑客Day1

sed命令

sed的工作流

语法

1
sed [option] [sed内置命令字符] [file]

选项

1
2
3
4
5
6
7
-n 取消默认sed的输出,常与sed内置命令p一起使用

-i 直接修改结果写入文件,不用-i,sed修改的是内存数据

-e 多次编辑,不需要管道符了

-r 支持拓展正则,sed默认支持基本正则

sed内置命令字符

sed的内置命令字符用于对文件进行不同的操作功能,如对文件增删改查

sed的内置命令字符 解释
a append,对文本追加,在指定行后面添加一行/多行文本
d Delete,删除匹配行
i insert,插入文本,在指定行前添加一行/多行文本
p print,打印匹配行的内容,通常与-n参数一起使用
s/正则/替换内容/g或者s#正则#替换内容#g或者s@正则@替换内容@g 匹配正则内容,然后替换内容(支持正则),结尾g代表全局匹配

匹配范围

范围 解释
空地址 全文处理,如:使用a时不指定行,则会在每一行后添加内容
单地址 指定文件某一行,如:1a,在第一行后添加内容
/pattern/ 被模式匹配到的每一行
范围区间 10,20 十到二十行 ;10,+5第10行向下5行 ;/pattern1/,/pattern2/匹配多个模式
步长 1~2表示1,3,5,7,9…奇数行;2~2两个步长表示2,4,6,8…偶数行

内置命令实践

准备数据文件sed.txt

1

配合正则表达实践

1

awk命令

awk是一个强大的Linux命令,有强大的文本格式化能力,好比将一些文本数据格式化成excel表的样式。

也是一行一行处理

  1. awk默认以空格为分隔符,且多个空格识别为一个空格作为分隔符
  2. awk是按行处理文件,一行处理完毕,处理下一行,根据用户指定的分隔符去工作,没有指定则默认空格
  3. 指定了分隔符后,awk把每一行切割后的数据对应到内置变量

awk早期在Unix上实现,awk是gawk,GUN awk的意思;

awk更是一门编程语言,支持条件判断、数组、循环等功能。

语法

1
2
awk [option] 'pattern{action}' file ...
#awk+awk可选参数、选项+模式{动作}+文件/数据
  • 最常用的action是:print/printf,即打印

选项

1
2
3
-F 指定分割字段符
-v 定义或修改一个awk内部的变量
-f 从脚本文件中读取awk命令

awk内置变量

awk ‘{print $2}’,没有使用参数和模式时,$2表示输出文本的第二列信息。

1
2
3
4
5
6
7
8
9
10
$0 代表一整行
$1 $2 $3 ... 代表第一列第二列第三列...(第一个字段、第二个、第三个.....)

$NF 代表最后一列(最后一个字段)
$(NF-1) 代表倒数第二列(倒数第二个字段)
FS 字段分隔符,默认是空格
NF(Number of fields) 分割后,当前行一共有多少个字段
NR(Number of records) 当前记录数、行数
#更多内置变量可以通过man手册查看
man awk

想要输入第一列第二列第三列时,$1$2$3用逗号隔开,输出的结果就不会挨在一起而是有默认空格分隔。

awk自定义输出内容在单引号中使用双引号括起来,如:

1
awk '{print "第一列:"$1,"第二列:"$2}'

实践

准备文件awk1.txt

1
2
3
4
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4

显示文件第五行

NR==5

=在Linux表示修改变量值,==表示关系运算符

1
awk 'NR==5{print $0}' awk1.txt

执行演示

1

显示文件第二行到第六行

1
awk 'NR==2,NR==6{print $0}' awk1.txt

执行演示

1

为文件每一行添加行号

1
awk '{print NR,$0}' awk1.txt

执行演示

1

显示文件第一列、倒数第三列、最后一列

NF

1
awk '{print $1,$(NF-2),$NF'

执行演示

1

使用awk取出ip地址

利用awk以空格为分隔符的特性

ipconfig eth0

1
ipconfig eth0|awk 'NR==2{print $2}'

执行演示

1

替换空格为其他分隔符

准备文件awk2.txt

1
2
3
a:b:c:d
1:2:3:4
x:x:x:x

awk的分隔符有两种

  • 输入分隔符,awk默认是空格、空白字符,英文是field separator,变量名为FS
  • 输出分隔符,output field separator,简称OFS

FS输入分隔符

使用参数可以指定分隔符

1
-F “<分隔符>”
实例

输出第一列和最后一列

1
awk -F ":" '{print $1,$NF}' awk2.txt

通过修改awk内置变量分隔符来实现指定分隔符

1
-v FS=“<分隔符>”

执行演示

1
2
3
4
5
6
7
8
[root@localhost ~]# cat awk2.txt
a:b:c:d
1:2:3:4
x:x:x:x
[root@localhost ~]# awk -F ":" '{print $1,$NF}' awk2.txt
a d
1 4
x x
实例

输出第二列和倒数第二列

1
awk -v FS=":" '{print $2,$(NF-1)}' awk2.txt

执行演示

1
2
3
4
5
6
7
8
[root@localhost ~]# cat awk2.txt
a:b:c:d
1:2:3:4
x:x:x:x
[root@localhost ~]# awk -v FS=":" '{print $2,$(NF-1)}' awk2.txt
b c
2 3
x x

OFS输出分隔符

当我们在输出使用逗号时,默认使用空格分割

awk -F “:” ‘{print $1,$2,$3,$4}’ awk2.txt

如果需要修改逗号的默认输出分隔符,我们可以修改OFS变量

1
awk -F ":" -v OFS="---" '{print $1,$2,$3,$4}' awk2.txt

执行演示

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# awk -F ":"  '{print $1,$2,$3,$4}' awk2.txt
a b c d
1 2 3 4
x x x x
[root@localhost ~]# cat awk2.txt
a:b:c:d
1:2:3:4
x:x:x:x
[root@localhost ~]# awk -F ":" -v OFS="---" '{print $1,$2,$3,$4}' awk2.txt
a---b---c---d
1---2---3---4
x---x---x---x

awk内置命令补充

awk变量分为

  • 内置变量
  • 自定义变量
1
2
3
4
5
6
RS 输入记录分隔符(输入换行符),指定输入时的换行符
ORS 输出记录分隔符(输出换行符),指定输出时的换行符
FNR 各文件分别技术的行号
FILENAME 当前文件名
ARGC 命令行参数的个数
ARGV 数组,保存的是命令行所给定的各参数

实践

处理多个文件显示行号

当作整体的情况

1
awk '{print NR,$0}' awk1.txt awk2.txt

执行演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@localhost ~]# cat awk1.txt
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
[root@localhost ~]# cat awk2.txt
a:b:c:d
1:2:3:4
x:x:x:x
[root@localhost ~]# awk '{print NR,$0}' awk1.txt awk2.txt
1 a1 a2 a3 a4
2 b1 b2 b3 b4
3 c1 c2 c3 c4
4 d1 d2 d3 d4
5 a:b:c:d
6 1:2:3:4
7 x:x:x:x

RS 更换输入换行分隔符

1
awk -v RS=" " {print $0} awk1.txt

执行演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@localhost ~]# cat awk1.txt
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
[root@localhost ~]# awk -v RS=" " '{print $0}' awk1.txt
a1
a2
a3
a4
b1
b2
b3
b4
c1
c2
c3
c4
d1
d2
d3
d4

ORS 更换输出换行分隔符

1
awk -v ORS=" " '{print $0}' awk1.txt

执行演示

1
2
3
4
5
6
7
8
9
[root@localhost ~]# awk '{print $0}' awk1.txt
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
[root@localhost ~]# awk -v ORS=" " '{print $0}' awk1.txt
a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4 d1 d2 d3 d4 [root@localhost ~]#
[root@localhost ~]# awk -v ORS="换行符" '{print $0}' awk1.txt
a1 a2 a3 a4换行符b1 b2 b3 b4换行符c1 c2 c3 c4换行符d1 d2 d3 d4换行符[root@localhost ~]#

数组ARGV变量的使用

BEGIN 模式,表示做什么事前先做什么事

1
awk 'BEGIN{print "这句话先做!"} {print $0}' awk1.txt

ARGV

1
2
3
4
awk 'BEGIN{print "这句话先做!"} {print ARGV[0],$0}' awk1.txt
awk 'BEGIN{print "这句话先做!"} {print ARGV[1],$0}' awk1.txt
awk 'BEGIN{print "这句话先做!"} {print ARGV[2],$0}' awk1.txt
awk 'BEGIN{print "这句话先做!"} {print ARGV[3],$0}' awk1.txt

执行演示

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
[root@localhost ~]# awk 'BEGIN{print "这句话先做"} {print $0}' awk1.txt
这句话先做
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
########
[root@localhost ~]# awk 'BEGIN{print "这句话先做!"} {print ARGV[0],$0}' awk1.txt这句话先做!
awk a1 a2 a3 a4
awk b1 b2 b3 b4
awk c1 c2 c3 c4
awk d1 d2 d3 d4
[root@localhost ~]# awk 'BEGIN{print "这句话先做!"} {print ARGV[1],$0}' awk1.txt这句话先做!
awk1.txt a1 a2 a3 a4
awk1.txt b1 b2 b3 b4
awk1.txt c1 c2 c3 c4
awk1.txt d1 d2 d3 d4
[root@localhost ~]# awk 'BEGIN{print "这句话先做!"} {print ARGV[2],$0}' awk1.txt这句话先做!
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
[root@localhost ~]# awk 'BEGIN{print "这句话先做!"} {print ARGV[3],$0}' awk1.txt这句话先做!
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4

从上面的结果我们可以看出数组ARGV[0],ARGV[1]分别存储的是命令awk,文件名awk1.txt

再通过一条命令就可以理解ARGV[]数组了

1
awk '{print ARGV[0],ARGV[1],ARGV[2]}' awk1.txt awk2.txt

执行演示

1
2
3
4
5
6
7
8
[root@localhost ~]# awk '{print ARGV[0],ARGV[1],ARGV[2]}' awk1.txt awk2.txt
awk awk1.txt awk2.txt
awk awk1.txt awk2.txt
awk awk1.txt awk2.txt
awk awk1.txt awk2.txt
awk awk1.txt awk2.txt
awk awk1.txt awk2.txt
awk awk1.txt awk2.txt

awk自定义变量

方法一 在awk中使用-v定义

1
awk -v var="这是一个变量" '{print var,$1}' awk2.txt

方法二 在程序中直接定义(两种写法)

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# awk '{var1="变量1";var2="变量2";print var1,var2,$0}' awk1.txt
变量1 变量2 a1 a2 a3 a4
变量1 变量2 b1 b2 b3 b4
变量1 变量2 c1 c2 c3 c4
变量1 变量2 d1 d2 d3 d4
[root@localhost ~]# awk '{var1="变量1";var2="变量2"}{print var1,var2,$0}' awk1.txt
变量1 变量2 a1 a2 a3 a4
变量1 变量2 b1 b2 b3 b4
变量1 变量2 c1 c2 c3 c4
变量1 变量2 d1 d2 d3 d4

方法三 间接引用shell变量(必须加BEGIN动作)

1
2
var=变量
awk -v var=$var 'BEGIN{print var}'

格式化

print只能简单的输出文本,并不能美化或者或者修改格式

prinf格式化输出

printf与print的区别

  1. printf需要指定format
  2. format用于指定后面的每个item的输出格式
  3. printf语句不会自动打印换行符
1
2
3
4
5
awk '{print $0}' awk1.txt
awk '{printf $0}' awk1.txt
#####
awk '{print $0}' awk1.txt
awk '{printf "%s\n",$0}' awk1.txt

执行演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@localhost ~]# awk '{print $0}' awk1.txt
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
[root@localhost ~]# awk '{printf $0}' awk1.txt
a1 a2 a3 a4b1 b2 b3 b4c1 c2 c3 c4d1 d2 d3 d4[root@localhost ~]#
##########
[root@localhost ~]# awk '{print $0}' awk1.txt
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4
[root@localhost ~]# awk '{printf "%s\n",$0}' awk1.txt
a1 a2 a3 a4
b1 b2 b3 b4
c1 c2 c3 c4
d1 d2 d3 d4

使用%s\n可以实现print的换行

format的使用

format格式的指示符都以%开头,后面跟一个字符

1
2
3
4
5
6
7
8
9
10
11
12
%c 显示字符的ASCII码
%d,%i 匹配十进制整数
%e,%E 科学计数显示数值
%f 显示浮点数
%g,%G 以科学计数法的格式或浮点数的格式显示数值
%s 匹配字符串
%v 无字符整数
%% 显示%本身

printf修饰符
- 左对齐,默认是右对齐
+ 显示数值符号,printf "%+d"

针对多个变量进行格式化

Linux中使用printf命令格式化字符

1
printf "%s" a,b,c,d
1
2
3
4
[root@localhost ~]# printf "%d\n" 1 2 3
1
2
3

awk中使用printf格式化字符

1
2
awk 'BEGIN{printf "%d\n",1,2,3}' 
awk 'BEGIN{printf "%d\n%d\n%d\n",1,2,3}'
1
2
3
4
5
6
[root@localhost ~]# awk 'BEGIN{printf "%d\n",1,2,3}'
1
[root@localhost ~]# awk 'BEGIN{printf "%d\n%d\n%d\n",1,2,3}'
1
2
3