shell 脚本- awk工具

[toc]bash


# 正则三剑客- awkpost

## awk与sed、grep的不一样之处是支持分段处理;测试

### 创建测试环境,建立一个awk目录并copy passwd到 awk目录下。编码

```
[root@localhost ~]# cd awk
[root@localhost awk]#  cp /etc/passwd awk/test.txt.net

[root@localhost awk]# awk -F ':' '{print $1}' test.txt
```
### 1. -F是制定分隔符,print为打印动做,用来打印某个字段,$1为第1个字段,$2为第2个字段,以此类推,但$0比较特殊,它表示整行:排序

```字符串

# awk -F ‘:’ ‘{print $1}’ passwd               -F:指定分隔符 //打印passwd的第一段
$1:第一段 ,$2:第二段,$0:整行
# awk -F ‘:’ ‘{print $0}’ passwd              -F:指定分隔符 //打印passwd的整行所有内容
若是不指定分隔符,默认是空格
# awk -F ‘:’ ‘{print $1,$3,$4}’ passwd                //同时打印第1,3,4段
#awk -F ‘:’ ‘{print $1“#”$3“#”$4}’ passwd          //指定打印结果以某个字符分割
```
![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/AlAe6d2iEd.png?imageslim)
![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/I46Gj0Hmeb.png?imageslim)get

### 2. -F 后面紧跟单引号,单引号内制定分隔符,print的动做要用{}括起来,能够自定义内容,但内容要加双引号。数学

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/JbfFbaLfLC.png?imageslim)for循环

### 3.匹配字符或者字符串
示例命令:

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180520/keFGK91egc.png?imageslim)

```
[root@localhost awk]# awk '/oo/' test.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
setroubleshoot:x:991:986::/var/lib/setroubleshoot:/sbin/nologin
```
这和sed的用法类似,实现grep功能,没有颜色显示,这里还能够匹配某一段,这里~就是匹配的意思

```
[root@localhost awk]# awk -F ':' '$1 ~/oo/' test.txt
root:x:0:0:root:/root:/bin/bash
setroubleshoot:x:991:986::/var/lib/setroubleshoot:/sbin/nologin
```
4.awk支持特殊字符+等,且没必要和grep那样+E,sed +r
![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/LjBHjA61C0.png?imageslim)

5. awk支持多个表达式,下例中awk匹配完root,再匹配test,它还能够只打印所匹配的段。
```
[root@localhost awk]# awk -F ':' '/root/ {print $1,$2} /test/ {print $1,$3}' test.txt
root x
operator x
test 1002
```
### 6. 条件操做符

* awk中是能够用逻辑符号判断的,好比 ‘==’ 就是等于,也能够理解为 ‘精确匹配’ 另外也有 >, ‘>=, ‘<, ‘<=, ‘!= 等等,值得注意的是,在和数字比较时,若把比较的数字用双引号引发来后,那么awk不会认为是数字,而认为是字符,不加双引号则认为是数字。
示例:

```
[root@localhost awk]# awk -F ':' '$3>=1000 {print $0}' test.txt
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash
```

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/J3bAaEm6FJ.png?imageslim)

* 这里1000和“1000”的区别,“1000”是字符串,按照ASCII码来比较大小,这就和sort排序是同样的了

#### ASCII比较大小

```
ASCII比较大小的时候,是比较两个数中的第一个字符 
1)经常使用字符有128个,编码从0到127。 
2)控制字符:0~3一、127,共33个,不可显示; 
3)普通字符:95个,包括10个阿拉伯数字、52个英文大小写字母、33个运算符。 
4)每一个字符占一个字节,7位,最高位为0。 
常见ASCII码的大小规则,0-9<A-Z<a-z: 
1)数字比字母要小。如 “7”<“F” 
2)数字0比数字9要小,并按0到9顺序递增。如 “3”<“8” 
3)字母A比字母Z要小,并按A到Z顺序递增。如“A”<“Z” 
4)同个字母的大写字母比小写字母要小32。如“A”<“a” 
记住几个常见字母的ASCII码大小: 
“A”为65;“a”为97;“0”为48;
```

* != 为不匹配,除了针对某一个段的字符进行逻辑比较外,还能够两个段之间进行逻辑比较:

```
[root@localhost awk]# awk -F ':' '$7!="/sbin/nologin" {print $0}' test.txt
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash
```
* $3<$4,$3==$4等进行比较

```
[root@localhost awk]# awk -F ':' '$3<$4' test.txt
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
```
* 还可使用&&和||,表示而且和或者,以及~匹配。

```
[root@localhost awk]# awk -F ':' '$3>"5"&& $4<"7"' test.txt
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
```

```
[root@localhost awk]# awk -F ':' '$3>1000 || $7~"/bash"' test.txt
root:x:0:0:root:/root:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash
[root@localhost awk]# awk -F ':' '$3>1000 || $7 ~/bash/' test.txt
root:x:0:0:root:/root:/bin/bash
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
xavi:x:1000:1000:xavi,xavi's office,62580558,62589906:/home/xavi:/bin/bash
xavidsf:x:1001:1001:xavi:/home/xavidsf:/bin/bash
test:x:1002:1002::/home/test:/bin/bash
Ding:x:1003:1003::/home/Ding:/bin/bash 
```
### 7 awk的内置变量

* awk经常使用的变量有:OSF、NF和NR。OFS与-F选项功能相似,用来定义分隔符,可是它是用在输出时候定义。NF表示用分隔符分隔后一共多少行,NR表示行号。

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/miJCb1Aa16.png?imageslim)

* 嵌套if语句

```
[root@localhost awk]# awk -F ':' '{OFS="#"} {if ($3>1000) {print $1,$2,$3,$4}}' /etc/passwd
nfsnobody#x#65534#65534
xavidsf#x#1001#1001
test#x#1002#1002
Ding#x#1003#1003
```
* NR表示行号,NF表示多少段
- [ ] #awk -F ':' '{print NR":"$0}' test.txt
- [ ] awk -F ':' '{print NF}' test.txt

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/HFfIjKF7Gm.png?imageslim)
![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/8fEm04H9K3.png?imageslim)

* NR还能够做为判断条件,显示10行;

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/k24B6hA4jJ.png?imageslim)

* NR配合段匹配一个使用,NR也是同理使用

```
[root@localhost awk]# awk -F ':' 'NR<=10 && $1 ~ /root|sync/' test.txt
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
```
### 8 awk 的数学运算

* =与==的区别,一个是赋值,即更改某些段的数值或字符,==是一个是判断

![mark](http://p0weeraap.bkt.clouddn.com/xavi2017/180117/0DAc21FjeD.png?imageslim)
* 没有冒号,能够在OFS中定义

```
[root@localhost awk]# head -n 3 test.txt |awk -F ':' '{OFS=":"} $1="root"'
root:x:0:0:root:/root:/bin/bash
root:x:1:1:bin:/bin:/sbin/nologin
root:x:2:2:daemon:/sbin:/sbin/nologin
```
* awk对各段的值进行数学运算,示例以下:

``` [root@localhost awk]# head -n 3 test.txt |awk -F ':' '{$7=$3+$4;print $0}' root x 0 0 root /root 0 bin x 1 1 bin /bin 2 daemon x 2 2 daemon /sbin 4 ``` * awk计算某个段的总和,这里的END要注意一下,表示全部的行都已经执行,这是awk特有的语法,其实awk连同sed均可以写成一个脚本文件,并且有他们特有的语法,在awk中使用if判断、for循环都是能够的。 ``` [root@localhost awk]# awk -F ':' '{(tot=tot+$3)}; END {print tot}' /etc/passwd 82235 ```  

相关文章
相关标签/搜索