今天我在学习awk的时候,使用awk来取df命令中磁盘利用率,想必这非常简单,但是指定分隔符的写法不同,其中的奥妙也不同,接下来带大家一起探索其中的奥妙。
首先我们使用下面两种不同的写法中,都可以取得df命令中磁盘利用率
[root@ubuntu2004 ~]#df | awk -F" +|%" '{print $5}'
Use
0
1
45
0
0
0
23
100
100
100
100
100
100
0
[root@ubuntu2004 ~]#df | awk -F"[ %]+" '{print $5}'
Use
0
1
45
0
0
0
23
100
100
100
100
100
100
0
但是我们去打印第六列,看看会有什么不同
[root@ubuntu2004 ~]#df | awk -F" +|%" '{print $6}'
[root@ubuntu2004 ~]#df | awk -F"[ %]+" '{print $6}'
Mounted
/dev
/run
/
/dev/shm
/run/lock
/sys/fs/cgroup
/boot
/snap/core20/2264
/snap/core20/2015
/snap/lxd/24061
/snap/snapd/20290
/snap/lxd/21835
/snap/snapd/21465
/run/user/0
会发现第一种写法,它打印出来的是空的,而第二种写法,打印出来的是挂载目录的信息。
让我们再看看另外一个例子,会发现两种写法中,NF的取值不同
[root@ubuntu2004 ~]#cat a.txt
1 2% 4
1 2%3 4
Avail Use% Mounted
Filesystem Size Used Avail Use% Mounted on
[root@ubuntu2004 ~]#awk -F"[ %]+" '{print NF}' a.txt
3
4
3
7
[root@ubuntu2004 ~]#awk -F" +|%" '{print NF}' a.txt
4
4
4
8
接下来我们来分析一下原因
第一个 awk 命令使用 -F"[ %]+” 这意味着字段分隔符是一个或多个空格或百号。
- 第一行 1 2% 4 被分割为三个字段:1,2,4。输出是3.
- 第二行 1 2%3 4 被分割为四个字段:1,2,3,4。输出是4。
- 第三行 Avail use% Mounted 被分割为三个字段:Avail, Use%, Mounted。输出是3。
- 第四行 Filesystem size Used Avail Use% Mounted on 被分割为七个字段:Filesystem, Size,Used, Avail, Use%, Mounted, on。输出是7.
第二个 awk 命令使用 -F” +|%” 这意味着字段分隔符是一个或多个空格,或者是单个百分号。
- 第一行 1 2% 4 被分割为四个字段:1,2,空字段(因为%后面没有内容),4。输出是4。
- 第二行 1 2%3 4 被分割为四个字段:1,2,3,4。输出是4.
- 第三行 Avail use% Mounted 被分割为四个字段:Avail, Use,空字段(因为%后面没有内容),Mounted。输出是4。
- 第四行 Filesystem size Used Avail use% Mounted on 被分割为八个字段:Filesystem, Size, Used,Avail, Use,空字段(因为%后面没有内容),Mounted,on。输出是8.
这就解释了为什么两个 awk 命令的输出不同。第二个 awk 命令在每次遇到单独的百分号时都会创建一个空字段,而第一个 awk 命令则不会这样做。那么为什么会这样子呢,我们接着看
- 对于 awk -F"[ %]+" ,字段分隔符被定义为正则表达式"[ %]+",这意味着字段可以由一个或多个空格或百分号分隔。这里的 + 符号表示“一个或多个”的意思,方括号[ ]内的空格和百分号表示这两个字符都可以作为分隔符。
- 在这种情况下, awk 会将空格和百分号视为等效的分隔符,但它们会被合并处理而不是分别处理。这意味着,如果一行中有连续的空格或百分号,或者空格和百分号混合出现,它们会被视为一个单一的分隔符。因此,不会因为分隔符的不同而产生空字段。
- 例如,对于第一行文本1 2% 4,使用[ %]+ 作为分隔符, awk 会将这行分割为三个字段:1、2和4。这是因为 2% 和 4 之间的空格符合分隔符的定义,而 2% 中的百分号也被视为分隔符的一部分。由于这些分隔符连续出现(即使是不同类型的分隔符),它们被合并处理为一个分隔符,因此不会产生空字段。
总结来说, awk -F"[ %]+"命令不会分别以空格和百分号进行分割,而是将它们视为可以互换的分隔符,并且当它们连续出现时,会被合并处理为一个分隔符,从而避免产生空字段。
基于以上的逻辑,如果还不理解,我们也可以用离散数学中的知识来理解,我们先说离散数学中的几个概念
在离散数学中,“∨”和“∧”分别代表逻辑或(析取)和逻辑与(合取)。具体如下:
- 逻辑或(∨):这是命题的“析取”运算,通常被称为“或”,对应于集合的并集,它涵盖了所有满足至少一个条件的情况。在逻辑表达式中,如果有两个命题P和Q,那么“P ∨ Q”表示的是P和Q中至少有一个是真的。也就是说,如果P是真的,或者Q是真的,或者它们都是真的,那么“P ∨ Q”就是真的。
- 逻辑与(∧):这是命题的“合取”运算,通常被称为“与”。同样地,如果有命题P和Q,那么“P ∧ Q”表示的是P和Q都必须是真的。只有当P和Q同时为真时,“P ∧ Q”才为真。
所以接下来我们使用离散数学的逻辑或和逻辑与来理解以上的知识点
我们假设:
- p:使用空格作为分隔符
- q:使用%作为分隔符
那么awk -F"[ %]+" 的命题符号化为
- (p∧¬q)V(¬p∧q)
表示了使用空格作为分隔符或者使用%作为分隔符
awk -F" +|%" 的命题符号化为
- pVq
表示使用空格作为分隔符或者使用%作为分隔符,或者两者都可能发生