上传文件至 awk
This commit is contained in:
parent
68dcc3fb25
commit
b8a8bbf538
527
awk/awk-基础.md
Normal file
527
awk/awk-基础.md
Normal file
@ -0,0 +1,527 @@
|
||||
<h2><center>Shell awk</center></h2>
|
||||
|
||||
------
|
||||
|
||||
## 一:AWK
|
||||
|
||||
### 1. awk 介绍
|
||||
|
||||
`awk`是一种编程语言,用于在`linux/unix`下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是`linux/unix`下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。
|
||||
|
||||
`awk`的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。`awk`分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是`Alfred Aho`、`Brian Kernighan`、`Peter Weinberger`。`gawk`是`awk`的`GNU`版本,它提供了`Bell`实验室和`GNU`的一些扩展。
|
||||
|
||||
### 2. 语法格式
|
||||
|
||||
```shell
|
||||
awk [-F field-separator] 'commands' input-file(s)
|
||||
awk [options] 'commands' var=value file(s)
|
||||
```
|
||||
|
||||
- `commands`是真正 AWK 命令,[-F域分隔符]是可选的。 `input-file(s)`是待处理的文件。
|
||||
- `awk`中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名`-F`域分隔符的情况下,默认的域分隔符是空格。
|
||||
|
||||
```shell
|
||||
awk -f awk-script-file input-file(s)
|
||||
awk [options] -f scriptfile var=value file(s)
|
||||
```
|
||||
|
||||
- `-f`选项加载`awk-script-file`中的`awk`脚本,`input-file(s)`是待处理的文件。
|
||||
- 将所有的`awk`命令插入一个脚本文件,使用`awk`命令解释器作为脚本的首行,相当于`shell`脚本首行的:`#!/bin/sh`可以换成:`#!/bin/awk`。通过执行脚本来调用。
|
||||
|
||||
### 3. 工作原理
|
||||
|
||||
`awk`工作流程可分为三个部分:
|
||||
|
||||
- 读输入文件之前执行的代码段(由`BEGIN`关键字标识)。
|
||||
- 主循环执行输入文件的代码段。
|
||||
- 读输入文件之后的代码段(由`END`关键字标识)。
|
||||
|
||||
**`awk`命令结构**
|
||||
|
||||
```shell
|
||||
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
|
||||
```
|
||||
|
||||
下图是`awk`的工作流程
|
||||
|
||||

|
||||
|
||||
- 通过关键字`BEGIN`执行`BEGIN`块的内容,即 BEGIN 后花括号 **{}** 的内容。
|
||||
- 完成`BEGIN`块的执行,开始执行`body`块。
|
||||
- 读入有 **\n** 换行符分割的记录。
|
||||
- 将记录按指定的域分隔符划分域,填充域,**$0** 则表示所有域(即一行内容),**$1** 表示第一个域,**$n** 表示第 n 个域。
|
||||
- 依次执行各`BODY`块,`pattern`部分匹配该行内容成功后,才会执行`awk-commands`的内容。
|
||||
- 循环读取并执行各行直到文件结束,完成`body`块执行。
|
||||
- 开始`END`块执行,`END`块可以输出最终结果。
|
||||
|
||||
**开始块**
|
||||
|
||||
开始块的语法格式如下:
|
||||
|
||||
```shell
|
||||
BEGIN {awk-commands}
|
||||
```
|
||||
|
||||
开始块就是在程序启动的时候执行的代码部分,并且它在整个过程中只执行一次。
|
||||
|
||||
一般情况下,我们可以在开始块中初始化一些变量。
|
||||
|
||||
`BEGIN`是`AWK`的关键字,因此它必须是大写的。
|
||||
|
||||
**注意:**
|
||||
|
||||
开始块部分是可选的,你的程序可以没有开始块部分。
|
||||
|
||||
**主体块(BODY)**
|
||||
|
||||
主体部分的语法格式如下:
|
||||
|
||||
```shell
|
||||
/pattern/ {awk-commands}
|
||||
```
|
||||
|
||||
对于每一个输入的行都会执行一次主体部分的命令。
|
||||
|
||||
默认情况下,对于输入的每一行,`AWK`都会执行命令。但是,我们可以将其限定在指定的模式中。
|
||||
|
||||
**注意**:
|
||||
|
||||
在主体块部分没有关键字存在。
|
||||
|
||||
**结束块(END)**
|
||||
|
||||
结束块的语法格式如下:
|
||||
|
||||
```shell
|
||||
END {awk-commands}
|
||||
```
|
||||
|
||||
结束块是在程序结束时执行的代码。`END`也是`AWK`的关键字,它也必须大写。 与开始块相似,结束块也是可选的。
|
||||
|
||||
**示例:**
|
||||
|
||||
先创建一个名为 marks.txt 的文件。其中包括序列号、学生名字、课程名称与所得分数。
|
||||
|
||||
```shell
|
||||
1) 张三 语文 80
|
||||
2) 李四 数学 90
|
||||
3) 王五 英语 87
|
||||
```
|
||||
|
||||
接下来,我们将使用 AWK 脚本来显示输出文件中的内容,同时输出表头信息。
|
||||
|
||||
```bash
|
||||
awk 'BEGIN{printf "序号\t名字\t课程\t分数\n"} {print}' marks.txt
|
||||
```
|
||||
|
||||
执行以上命令,输出结果如下:
|
||||
|
||||
```shell
|
||||
序号 名字 课程 分数
|
||||
1) 张三 语文 80
|
||||
2) 李四 数学 90
|
||||
3) 王五 英语 87
|
||||
```
|
||||
|
||||
程序开始执行时,`AWK`在开始块中输出表头信息。在主体块中,`AWK`每读入一行就将读入的内容输出至标准输出流中,一直到整个文件被全部读入为止。
|
||||
|
||||
### 4. awk 选项
|
||||
|
||||
```shell
|
||||
-F fs or --field-separator fs
|
||||
# 指定输入文件折分隔符,fs 是一个字符串或者是一个正则表达式,如 -F:。
|
||||
|
||||
-v var=value or --asign var=value
|
||||
# 赋值一个用户定义变量。
|
||||
|
||||
-f scripfile or --file scriptfile
|
||||
# 从脚本文件中读取 awk 命令。
|
||||
|
||||
-mf nnn and -mr nnn
|
||||
# 对 nnn 值设置内在限制,-mf 选项限制分配给 nnn 的最大块数目;-mr 选项限制记录的最大数目。这两个功能是 Bell 实验室版 awk 的扩展功能,在标准 awk 中不适用。
|
||||
|
||||
-W compact or --compat, -W traditional or --traditional
|
||||
# 在兼容模式下运行 awk。所以 gawk 的行为和标准的 awk 完全一样,所有的 awk 扩展都被忽略。
|
||||
|
||||
-W copyleft or --copyleft, -W copyright or --copyright
|
||||
# 打印简短的版权信息。
|
||||
|
||||
-W help or --help, -W usage or --usage
|
||||
# 打印全部 awk 选项和每个选项的简短说明。
|
||||
|
||||
-W lint or --lint
|
||||
# 打印不能向传统 unix 平台移植的结构的警告。
|
||||
|
||||
-W lint-old or --lint-old
|
||||
# 打印关于不能向传统 unix 平台移植的结构的警告。
|
||||
|
||||
-W posix
|
||||
# 打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当 fs 是一个空格时,将新行作为一个域分隔符;操作符 ** 和 **= 不能代替 ^ 和 ^=;fflush无效。
|
||||
|
||||
-W re-interval or --re-inerval
|
||||
# 允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
|
||||
|
||||
-W source program-text or --source program-text
|
||||
# 使用 program-text 作为源代码,可与 -f 命令混用。
|
||||
|
||||
-W version or --version
|
||||
# 打印 bug 报告信息的版本。
|
||||
```
|
||||
|
||||
### 5. 格式化打印
|
||||
|
||||
- print 和 printf 都是打印输出的,不过两者用法和显示上有些不同而已。
|
||||
|
||||
```shell
|
||||
print 格式:print item1,item2, ...
|
||||
printf格式:printf “FORMAT ”,item1,item2, ...
|
||||
```
|
||||
|
||||
- 逗号为分隔符时,显示的是空格;
|
||||
- 分隔符分隔的字段(域)标记称为域标识,用$0,$1,$2,...,$n表示,其中$0 为所有域,$1就是表示第一个字段(域),以此类推;
|
||||
|
||||
- 输出的各item可以字符串,也可以是数值,当前记录的字段,变量或awk 的表达式等;
|
||||
|
||||
- 如果省略了item ,相当于print $0
|
||||
|
||||
- 对于printf来说,其中格式化字符串包括两部分内容: 一部分是正常字符,这些字符将按原样输出; 另一部分是格式化规定字符, 以 **%** 开始, 后跟一个或几个规定字符,用来确定输出内容格式,必须指定 FORMAT,即必须指出后面每个itemsN 的输出格式,**printf** 时默认是不会换行的,而 **print** 函数默认会在每行后面加上 **\n** 换行符
|
||||
|
||||
| **格式符** | **说明** |
|
||||
| :--------: | :----------------------------------------------------------: |
|
||||
| %d | 十进制有符号整数 |
|
||||
| %u | 十进制无符号整数 |
|
||||
| %f | 浮点数 |
|
||||
| %s | 字符串 |
|
||||
| %c | 单个字符 |
|
||||
| %p | 指针的值 |
|
||||
| %e | 指数形式的浮点数 |
|
||||
| %x | %X 无符号以十六进制表示的整数 |
|
||||
| %o | 无符号以八进制表示的整数 |
|
||||
| %g | 自动选择合适的表示法 |
|
||||
| %% | 显示%自身 |
|
||||
| #[.#] | 第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f |
|
||||
| - | 左对齐(默认右对齐);%-15s,就是以左对齐方式显示15个字符长度 |
|
||||
| + | 显示数值的正负符号 %+d |
|
||||
|
||||
**示例:**
|
||||
|
||||
```bash
|
||||
# print 函数
|
||||
[root@wxin ~]# awk '{print "hello,awk"}'
|
||||
[root@wxin ~]# awk –F: '{print}' /etc/passwd
|
||||
[root@wxin ~]# awk –F: ‘{print “wang”}’ /etc/passwd
|
||||
[root@wxin ~]# awk –F: ‘{print $1}’ /etc/passwd
|
||||
[root@wxin ~]# awk –F: ‘{print $0}’ /etc/passwd
|
||||
[root@wxin ~]# awk –F: ‘{print $1”\t”$3}’ /etc/passwd
|
||||
[root@wxin ~]# date |awk '{print "Month: " $2 "\nYear: " $NF}'
|
||||
[root@wxin ~]# awk -F: '{print "username is: " $1 "\t uid is: " $3}' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd
|
||||
|
||||
# printf函数
|
||||
[root@wxin ~]# tail –3 /etc/fstab |awk ‘{print $2,$4}’
|
||||
[root@wxin ~]# awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd
|
||||
[root@wxin ~]# awk -F: ‘{printf "%s",$1}’ /etc/passwd
|
||||
[root@wxin ~]# awk -F: ‘{printf "%s\n",$1}’ /etc/passwd
|
||||
[root@wxin ~]# awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
|
||||
[root@wxin ~]# awk -F: ‘{printf "Username: %s\n",$1}’ /etc/passwd
|
||||
[root@wxin ~]# awk -F: ‘{printf “Username: %s,UID:%d\n",$1,$3}’ /etc/passwd
|
||||
[root@wxin ~]# awk -F: ‘{printf "Username: %15s,UID:%d\n",$1,$3}’ /etc/passwd
|
||||
[root@wxin ~]# awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’ /etc/passwd
|
||||
[root@wxin ~]# lsmod | awk -v FS=" " 'BEGIN{printf "%s %26s %10s\n","Module","Size","Used by"}{printf "%-20s %13d %5s %s\n",$1,$2,$3,$4}' /proc/modules
|
||||
```
|
||||
|
||||
### 6. awk 运算符
|
||||
|
||||
| 运算符 | 描述 |
|
||||
| :---------------------: | :------------------------------: |
|
||||
| = += -= *= /= %= ^= **= | 赋值 |
|
||||
| ?: | C条件表达式 |
|
||||
| \|\| | 逻辑或 |
|
||||
| && | 逻辑与 |
|
||||
| ~ 和 !~ | 匹配正则表达式和不匹配正则表达式 |
|
||||
| < <= > >= != == | 关系运算符 |
|
||||
| 空格 | 连接 |
|
||||
| + - | 加,减 |
|
||||
| * / % | 乘,除与求余 |
|
||||
| + - ! | 一元加,减和逻辑非 |
|
||||
| ^ *** | 求幂 |
|
||||
| ++ -- | 增加或减少,作为前缀或后缀 |
|
||||
| $ | 字段引用 |
|
||||
| in | 数组成员 |
|
||||
|
||||
**示例:**
|
||||
|
||||
过滤第一列大于2的行
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk '$1>2' log.txt
|
||||
3 Are you like awk
|
||||
This's a test
|
||||
10 There are orange,apple,mongo
|
||||
```
|
||||
|
||||
过滤第一列等于2的行
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk '$1==2 {print $1,$3}' log.txt
|
||||
2 is
|
||||
```
|
||||
|
||||
过滤第一列大于2并且第二列等于'Are'的行
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt
|
||||
3 Are you
|
||||
```
|
||||
|
||||
过滤练习
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '$3 == 0' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '$3 < 10' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '$NF == "/bin/bash"' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '$1 == "alice"' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '$1 ~ /alic/ ' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '$1 !~ /alic/ ' /etc/passwd
|
||||
[root@wxin ~]# df -P | grep '/' |awk '$4 > 25000'
|
||||
```
|
||||
|
||||
### 7. awk 变量
|
||||
|
||||
**`awk`内置变量**
|
||||
|
||||
| 变量 | 描述 |
|
||||
| :---------: | :--------------------------------------------------------: |
|
||||
| $n | 当前记录的第n个字段,字段间由FS分隔 |
|
||||
| $0 | 完整的输入记录 |
|
||||
| ARGC | 命令行参数的数目 |
|
||||
| ARGIND | 命令行中当前文件的位置(从0开始算) |
|
||||
| ARGV | 包含命令行参数的数组 |
|
||||
| CONVFMT | 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组 |
|
||||
| ERRNO | 最后一个系统错误的描述 |
|
||||
| FIELDWIDTHS | 字段宽度列表(用空格键分隔) |
|
||||
| FILENAME | 当前文件名 |
|
||||
| FNR | 各文件分别计数的行号 |
|
||||
| FS | 字段分隔符(默认是任何空格) |
|
||||
| IGNORECASE | 如果为真,则进行忽略大小写的匹配 |
|
||||
| NF | 一条记录的字段的数目 |
|
||||
| NR | 已经读出的记录数,就是行号,从1开始 |
|
||||
| OFMT | 数字的输出格式(默认值是%.6g) |
|
||||
| OFS | 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符 |
|
||||
| ORS | 输出记录分隔符(默认值是一个换行符) |
|
||||
| RLENGTH | 由match函数所匹配的字符串的长度 |
|
||||
| RS | 记录分隔符(默认是一个换行符) |
|
||||
| RSTART | 由match函数所匹配的字符串的第一个位置 |
|
||||
| SUBSEP | 数组下标分隔符(默认值是/034) |
|
||||
|
||||
**示例:**
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{print $0}' /etc/passwd # $0
|
||||
[root@wxin ~]# awk -F: '{print NR, $0}' /etc/passwd /etc/hosts # NR
|
||||
[root@wxin ~]# awk -F: '{print FNR, $0}' /etc/passwd /etc/hosts # FNR
|
||||
[root@wxin ~]# awk -F: '{print $0,NF}' /etc/passwd # NF
|
||||
[root@wxin ~]# awk -F: '/alice/{print $1, $3}' /etc/passwd # FS
|
||||
[root@wxin ~]# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd
|
||||
[root@wxin ~]# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd
|
||||
[root@wxin ~]# awk -F: '/alice/{print $1,$2,$3,$4}' /etc/passwd # OFS
|
||||
[root@wxin ~]# awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2,$3,$4}' passwd
|
||||
[root@wxin ~]# awk -F: 'BEGIN{RS=" "} {print $0}' a.txt # RS
|
||||
[root@wxin ~]# awk -F: 'BEGIN{ORS=""} {print $0}' passwd # ORS
|
||||
```
|
||||
|
||||
- 字段分隔符: FS OFS 默认空格或制表符
|
||||
- 记录分隔符: RS ORS 默认换行符
|
||||
|
||||
```bash
|
||||
# ORS 默认输出一条记录应该回车,加了一个空格
|
||||
[root@wxin ~]# awk 'BEGIN{ORS=" "} {print $0}' /etc/passwd # 将文件每一行合并为一行
|
||||
|
||||
[root@wxin ~]# head -1 /etc/passwd > passwd1
|
||||
[root@wxin ~]# cat passwd1
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
[root@wxin ~]# awk 'BEGIN{RS=":"} {print $0}' passwd1
|
||||
root
|
||||
x
|
||||
0
|
||||
0
|
||||
root
|
||||
/root
|
||||
/bin/bash
|
||||
|
||||
[root@wxin ~]# awk 'BEGIN{RS=":"} {print $0}' passwd1 |grep -v '^$' > passwd2
|
||||
|
||||
# 输出顺序号 NR, 匹配文本行号
|
||||
[root@wxin ~]# awk '{print NR,FNR,$1,$2,$3}' /etc/passwd
|
||||
1 1 root:x:0:0:root:/root:/bin/bash
|
||||
2 2 bin:x:1:1:bin:/bin:/sbin/nologin
|
||||
3 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
|
||||
4 4 adm:x:3:4:adm:/var/adm:/sbin/nologin
|
||||
5 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
|
||||
|
||||
# 指定输出分割符
|
||||
[root@wxin ~]# awk '{print $1,$2,$5}' OFS=" $ " /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 $ $
|
||||
adm:x:3:4:adm:/var/adm:/sbin/nologin $ $
|
||||
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin $ $
|
||||
```
|
||||
|
||||
**`awk`自定义变量(区分大小写)**
|
||||
|
||||
```shell
|
||||
在'{...}'前,需要用-v var=value:awk -v var=value '{...}'
|
||||
在program 中直接定义:awk '{var=vlue}'
|
||||
```
|
||||
|
||||
**`awk`使用外部变量**
|
||||
|
||||
在双引号的情况下使用
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# var="bash"
|
||||
[root@wxin ~]# echo "unix script" |awk "gsub(/unix/,\"$var\")"
|
||||
bash script
|
||||
```
|
||||
|
||||
在单引号的情况下使用
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# var="bash"
|
||||
[root@wxin ~]# echo "unix script" |awk 'gsub(/unix/,"'"$var"'")'
|
||||
bash script
|
||||
|
||||
[root@wxin ~]# df -h
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/mapper/cl-root 2.8T 246G 2.5T 9% /
|
||||
tmpfs 24G 20K 24G 1% /dev/shm
|
||||
/dev/sda2 1014M 194M 821M 20% /boot
|
||||
|
||||
[root@wxin ~]# df -h |awk '{ if(int($5)>5){print $6":"$5} }'
|
||||
/:9%
|
||||
/boot:20%
|
||||
|
||||
[root@wxin ~]# i=10
|
||||
[root@wxin ~]# df -h |awk '{ if(int($5)>'''$i'''){print $6":"$5} }'
|
||||
/boot:20%
|
||||
```
|
||||
|
||||
AWK 参数-v(建议)
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# echo "unix script" |awk -v var="bash" 'gsub(/unix/,var)'
|
||||
bash script
|
||||
|
||||
[root@wxin ~]# awk -v user=root -F: '$1 == user' /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
```
|
||||
|
||||
### 8. awk 脚本
|
||||
|
||||
**`awk`脚本定义格式**
|
||||
|
||||
```shell
|
||||
格式1:
|
||||
BEGIN{} pattern{} END{}
|
||||
|
||||
格式2:
|
||||
#!/bin/awk -f
|
||||
#add 'x' right
|
||||
BEGIN{} pattern{} END{}
|
||||
```
|
||||
|
||||
关于awk 脚本,需要注意两个关键词BEGIN和END。
|
||||
|
||||
- BEGIN{ 这里面放的是执行前的语句 }
|
||||
- END {这里面放的是处理完所有的行后要执行的语句 }
|
||||
- {这里面放的是处理每一行时要执行的语句}
|
||||
|
||||
- 格式1假设为`f1.awk`文件,格式2假设为`f2.awk`文件
|
||||
|
||||
```shell
|
||||
awk [-v var=value] f1.awk [file]
|
||||
f2.awk [-v var=value] [var1=value1] [file]
|
||||
```
|
||||
|
||||
- awk [-v var=value] f1.awk [file],把处理阶段放到一个文件而已,展开后就是普通的`awk`语句。
|
||||
- f2.awk [-v var=value] [var1=value1] [file] 中 [-v var=value] 是在`BEGIN`之前设置的变量值,[var1=value1]是在BEGIN过程之后进行的,也就是说直到首行输入完成后,这个变量才可用。
|
||||
|
||||
**示例:**
|
||||
|
||||
示例一:
|
||||
|
||||
创建一个文件(学生成绩表)
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# cat score.txt
|
||||
Marry 2143 78 84 77
|
||||
Jack 2321 66 78 45
|
||||
Tom 2122 48 77 71
|
||||
Mike 2537 87 97 95
|
||||
Bob 2415 40 57 62
|
||||
```
|
||||
|
||||
定义 awk 脚本
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# cat cal.awk
|
||||
#!/bin/awk -f
|
||||
#运行前
|
||||
BEGIN {
|
||||
math = 0
|
||||
english = 0
|
||||
computer = 0
|
||||
|
||||
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
|
||||
printf "---------------------------------------------\n"
|
||||
}
|
||||
#运行中
|
||||
{
|
||||
math+=$3
|
||||
english+=$4
|
||||
computer+=$5
|
||||
printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
|
||||
}
|
||||
#运行后
|
||||
END {
|
||||
printf "---------------------------------------------\n"
|
||||
printf " TOTAL:%10d %8d %8d \n", math, english, computer
|
||||
printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
|
||||
}
|
||||
|
||||
[root@wxin ~]# awk -f cal.awk score.txt
|
||||
NAME NO. MATH ENGLISH COMPUTER TOTAL
|
||||
---------------------------------------------
|
||||
Marry 2143 78 84 77 239
|
||||
Jack 2321 66 78 45 189
|
||||
Tom 2122 48 77 71 196
|
||||
Mike 2537 87 97 95 279
|
||||
Bob 2415 40 57 62 159
|
||||
---------------------------------------------
|
||||
TOTAL: 319 393 350
|
||||
AVERAGE: 63.80 78.60 70.00
|
||||
```
|
||||
|
||||
示例二:
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# vim f1.awk
|
||||
{if($3>=1000)print $1,$3}
|
||||
awk -F: -f f1.awk /etc/passwd
|
||||
|
||||
[root@wxin ~]# vim f2.awk
|
||||
#!/bin/awk –f
|
||||
# this is a awk script
|
||||
{if($3>=1000)print $1,$3}
|
||||
# chmod +x f2.awk
|
||||
f2.awk –F: /etc/passwd
|
||||
|
||||
[root@wxin ~]# vim test.awk
|
||||
#!/bin/awk –f
|
||||
{if($3 >=min && $3<=max)print $1,$3}
|
||||
#chmod +x test.awk
|
||||
test.awk -F: min=100 max=200 /etc/passwd
|
||||
```
|
||||
|
225
awk/awk-数组与函数.md
Normal file
225
awk/awk-数组与函数.md
Normal file
@ -0,0 +1,225 @@
|
||||
<h2><center>awk 数组与函数</center></h2>
|
||||
|
||||
------
|
||||
|
||||
## 一:数组
|
||||
|
||||
`awk`可以使用关联数组这种数据结构,索引可以是数字或字符串。
|
||||
|
||||
`awk`关联数 组也不需要提前声明其大小,因为它在运行时可以自动的增大或减小。
|
||||
|
||||
### 1. 语法格式
|
||||
|
||||
```shell
|
||||
array_name[index]=value
|
||||
```
|
||||
|
||||
- array_name:数组的名称
|
||||
- index:数组索引
|
||||
- value:数组中元素所赋予的值
|
||||
|
||||
### 2. 创建数组
|
||||
|
||||
定义了一个站点(sites)数组,该数组的索引为网站英文简称,值为网站访问地址。
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
sites["qfedu"]="www.qfedu.com";
|
||||
sites["google"]="www.google.com"
|
||||
print sites["qfedu"] "\n" sites["google"]
|
||||
}'
|
||||
www.qfedu.com
|
||||
www.google.com
|
||||
```
|
||||
|
||||
### 3. 访问数组
|
||||
|
||||
访问数组元素语法格式
|
||||
|
||||
```shell
|
||||
array_name[index]
|
||||
```
|
||||
|
||||
访问数组元素
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd
|
||||
root
|
||||
[root@wxin ~]# awk -F: '{username[i++]=$1} END{print username[1]}' /etc/passwd
|
||||
bin
|
||||
[root@wxin ~]# awk -F: '{username[i++]=$1} END{print username[0]}' /etc/passwd
|
||||
root
|
||||
```
|
||||
|
||||
按元数个数遍历
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}' /etc/passwd
|
||||
0 root
|
||||
1 bin
|
||||
2 daemon
|
||||
3 adm
|
||||
4 lp
|
||||
5 sync
|
||||
6 shutdown
|
||||
7 halt
|
||||
|
||||
[root@wxin ~]# awk -F: '{username[++x]=$1} END{for(i=1;i<=x;i++) print i,username[i]}' /etc/passwd
|
||||
1 root
|
||||
2 bin
|
||||
3 daemon
|
||||
4 adm
|
||||
5 lp
|
||||
6 sync
|
||||
7 shutdown
|
||||
8 halt
|
||||
9 mail
|
||||
10 operator
|
||||
```
|
||||
|
||||
按索引遍历
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
|
||||
17 sshd
|
||||
4 lp
|
||||
18 postfix
|
||||
5 sync
|
||||
19 mysql
|
||||
6 shutdown
|
||||
7 halt
|
||||
8 mail
|
||||
9 operator
|
||||
10 games
|
||||
20 nginx
|
||||
|
||||
[root@wxin ~]# awk -F: '{username[++x]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
|
||||
17 tss
|
||||
4 adm
|
||||
18 sshd
|
||||
5 lp
|
||||
19 postfix
|
||||
6 sync
|
||||
7 shutdown
|
||||
8 halt
|
||||
9 mail
|
||||
10 operator
|
||||
20 mysql
|
||||
11 games
|
||||
|
||||
# 注:变量i是索引
|
||||
```
|
||||
|
||||
### 4. 删除元素
|
||||
|
||||
删除数组元素语法格式
|
||||
|
||||
```shell
|
||||
delete array_name[index]
|
||||
```
|
||||
|
||||
**删除数组元素**
|
||||
|
||||
删除数组中的 google 元素(删除命令没有输出):
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
sites["qfedu"]="www.qfedu.com";
|
||||
sites["google"]="www.google.com"
|
||||
delete sites["google"];
|
||||
print fruits["google"]
|
||||
}'
|
||||
```
|
||||
|
||||
### 5. 多维数组
|
||||
|
||||
AWK 本身不支持多维数组,不过我们可以很容易地使用一维数组模拟实现多维数组。
|
||||
|
||||
如下示例为一个 3x3 的三维数组:
|
||||
|
||||
```shell
|
||||
100 200 300
|
||||
400 500 600
|
||||
700 800 900
|
||||
```
|
||||
|
||||
实例中,array0 存储 100,array0 存储 200 ,依次类推。
|
||||
|
||||
要在 array0 处存储 100, 使用: array["0,0"] = 100。
|
||||
|
||||
使用 0,0 作为索引,这并不是两个索引值,而是一个字符串索引 0,0。
|
||||
|
||||
**模拟二维数组**
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
array["0,0"] = 100;
|
||||
array["0,1"] = 200;
|
||||
array["0,2"] = 300;
|
||||
array["1,0"] = 400;
|
||||
array["1,1"] = 500;
|
||||
array["1,2"] = 600;
|
||||
# 输出数组元素
|
||||
print "array[0,0] = " array["0,0"];
|
||||
print "array[0,1] = " array["0,1"];
|
||||
print "array[0,2] = " array["0,2"];
|
||||
print "array[1,0] = " array["1,0"];
|
||||
print "array[1,1] = " array["1,1"];
|
||||
print "array[1,2] = " array["1,2"];
|
||||
}'
|
||||
|
||||
array[0,0] = 100
|
||||
array[0,1] = 200
|
||||
array[0,2] = 300
|
||||
array[1,0] = 400
|
||||
array[1,1] = 500
|
||||
array[1,2] = 600
|
||||
```
|
||||
|
||||
在数组上可以执行很多操作,比如,使用 asort 完成数组元素的排序,或者使用 asorti 实现数组索引的排序等等。
|
||||
|
||||
## 二:函数
|
||||
|
||||
awk的函数有许多,除了系统自带的内建函数还有就是用户自定义的函数。
|
||||
|
||||
**AWK 常用的函数**
|
||||
|
||||
```shell
|
||||
rand() # 返回0 和1 之间一个随机数
|
||||
srand() # 生成随机数种子
|
||||
int() # 取整数
|
||||
length([s]) # 返回指定字符串的长度
|
||||
sub(r,s,[t]) # 对t字符串进行搜索,r表示的模式匹配的内容,并将第一个匹配的内容替换为s
|
||||
gsub(r,s,[t]) # 对t字符串进行搜索,r表示的模式匹配的内容,并全部替换为s所表示的内容
|
||||
split(s,array,[r])# 以r为分隔符,切割字符串s,并将切割后的结果保存至array 所表示的数组中,第一个索引值为1, 第二个索引值为2,…也就是说awk的数组下标是从1开始编的
|
||||
substr(s,i,[n]): # 从s所表示的字符串中取子串,取法:从i表示的位置开始,取n个字符。
|
||||
systime() # 取当前系统时间,结果形式为时间戳。
|
||||
system() # 调用shell中的命令。空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。
|
||||
```
|
||||
|
||||
**自定义函数示例**
|
||||
|
||||
```shell
|
||||
function fname ( arg1,arg2 , ... ) {
|
||||
statements
|
||||
return expr
|
||||
}
|
||||
```
|
||||
|
||||
- fname为函数名,
|
||||
- arg1...为函数的参数,
|
||||
- statements是动作语言,
|
||||
- return expr为由 statements 的结果从而决定最终函数所显示的内容。
|
||||
|
||||
**自定义函数示例**
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# cat fun.awk
|
||||
function max(v1,v2) {
|
||||
v1>v2?var=v1:var=v2
|
||||
return var
|
||||
}
|
||||
BEGIN{a=3;b=2;print max(a,b)}
|
||||
awk –f fun.awk
|
||||
```
|
||||
|
440
awk/awk-流程控制.md
Normal file
440
awk/awk-流程控制.md
Normal file
@ -0,0 +1,440 @@
|
||||
<h2><center>awk 流程控制</center></h2>
|
||||
|
||||
------
|
||||
|
||||
## 一:流程控制
|
||||
|
||||
### 1. 条件
|
||||
|
||||
#### 1. if 语句
|
||||
|
||||
**`if`条件语句语法格式**
|
||||
|
||||
```shell
|
||||
if (condition)
|
||||
action
|
||||
```
|
||||
|
||||
**使用花括号语法格式**
|
||||
|
||||
```shell
|
||||
if (condition)
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}
|
||||
|
||||
{if(表达式){语句1;语句2;...}}
|
||||
```
|
||||
|
||||
**示例:**
|
||||
|
||||
判断数字是奇数还是偶数
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {num = 10; if (num % 2 == 0) printf "%d 是偶数\n", num }'
|
||||
10 是偶数
|
||||
```
|
||||
|
||||
判断 root 是不是 administrator
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
|
||||
root is administrator.
|
||||
```
|
||||
|
||||
统计系统用户数
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{if($3>0 && $3<1000){count++;}} END{print count}' /etc/passwd
|
||||
20
|
||||
```
|
||||
|
||||
#### 2. if - else 语句
|
||||
|
||||
**`if - else`条件语句语法格式**
|
||||
|
||||
```shell
|
||||
if (condition)
|
||||
action1
|
||||
else
|
||||
action2
|
||||
```
|
||||
|
||||
**使用花括号语法格式**
|
||||
|
||||
```shell
|
||||
{if (condition)
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}}
|
||||
|
||||
{if(表达式){语句1;语句2;...}else{语句1;语句2;...}}
|
||||
```
|
||||
|
||||
**示例:**
|
||||
|
||||
判断数字是奇数还是偶数
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
num = 11;
|
||||
if (num % 2 == 0) printf "%d 是偶数\n", num;
|
||||
else printf "%d 是奇数\n", num
|
||||
}'
|
||||
|
||||
11 是奇数
|
||||
```
|
||||
|
||||
判断用户为root就打印用户名否则打印shell类型
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
|
||||
root
|
||||
/sbin/nologin
|
||||
/sbin/nologin
|
||||
/sbin/nologin
|
||||
/sbin/nologin
|
||||
/bin/sync
|
||||
/sbin/shutdown
|
||||
```
|
||||
|
||||
统计管理员数量和系统用户数量
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数: "count ; print "系统用户数: "i}' /etc/passwd
|
||||
管理员个数: 1
|
||||
系统用户数: 20
|
||||
```
|
||||
|
||||
#### 3. if - else - if 语句
|
||||
|
||||
**`if - else - if`条件语句语法格式**
|
||||
|
||||
```shell
|
||||
{if (condition1)
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}
|
||||
else if (condition2)
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}
|
||||
else if (condition3)
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}
|
||||
else
|
||||
{
|
||||
action1;
|
||||
action2;
|
||||
...
|
||||
}}
|
||||
|
||||
{if(表达式1){语句1;语句2;...}else if(表达式2){语句1;语句2;...}else if(表达式3){语句1;语句2;...}else{语句1;语句2;...}}
|
||||
```
|
||||
|
||||
**示例:**
|
||||
|
||||
多级判断结果
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
a=30;
|
||||
if (a==10)
|
||||
print "a = 10";
|
||||
else if (a == 20)
|
||||
print "a = 20";
|
||||
else if (a == 30)
|
||||
print "a = 30";
|
||||
}'
|
||||
|
||||
a = 30
|
||||
```
|
||||
|
||||
统计管理员,系统,普通用户数量
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
|
||||
1
|
||||
|
||||
20
|
||||
|
||||
[root@wxin ~]# awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数: "i; print "普通用个数: "k; print "系统用户: "j}' /etc/passwd
|
||||
管理员个数: 1
|
||||
普通用个数:
|
||||
系统用户: 20
|
||||
```
|
||||
|
||||
### 2. 循环
|
||||
|
||||
#### 1. for 循环
|
||||
|
||||
**语法:**
|
||||
|
||||
```shell
|
||||
for(variable addignment; condition; iteration peocess)
|
||||
{
|
||||
statement1
|
||||
statement2
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
for 语句首先执行初始化动作( initialisation ),然后再检查条件( condition )。如果条件为真,则执行动作( action ),然后执行递增( increment )或者递减( decrement )操作。只要条件为 true 循环就会一直执行。每次循环结束都会进条件检查,若条件为 false 则结束循环。
|
||||
|
||||
**示例:**
|
||||
|
||||
For 循环输出数字 1 至 5
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
```
|
||||
|
||||
For 循环输出数字 1 至 9 的奇数之和
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# echo "hello" | awk '
|
||||
{
|
||||
total = 0
|
||||
for(i=1; i<10; i++)
|
||||
{
|
||||
if(i % 2 == 0)
|
||||
{
|
||||
continue
|
||||
}
|
||||
total = total + i
|
||||
}
|
||||
print "total=", total
|
||||
}'
|
||||
```
|
||||
|
||||
将每行打印10次
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' /etc/passwd
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
root:x:0:0:root:/root:/bin/bash
|
||||
```
|
||||
|
||||
分别打印每行的每列
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' /etc/passwd
|
||||
root
|
||||
x
|
||||
0
|
||||
0
|
||||
root
|
||||
/root
|
||||
/bin/bash
|
||||
bin
|
||||
x
|
||||
1
|
||||
1
|
||||
bin
|
||||
/bin
|
||||
/sbin/nologin
|
||||
```
|
||||
|
||||
#### 2. while 循环
|
||||
|
||||
**语法:**
|
||||
|
||||
```shell
|
||||
while(condition)
|
||||
{
|
||||
statement1
|
||||
statement2
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
While 循环首先检查条件 condition 是否为 true ,若条件为 true 则执行动作 action。此过程一直重复直到条件 condition 为 flase 才停止。
|
||||
|
||||
**示例:**
|
||||
|
||||
While 循环输出数字 1 到 5
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {i = 1; while (i < 6) { print i; ++i } }'
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
|
||||
[root@wxin ~]# awk 'BEGIN{ i=1; while(i<=5){print i; i++} }'
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
```
|
||||
|
||||
While 循环输出数字 1 至 9 的奇数之和
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# echo "hello" | awk '
|
||||
{
|
||||
total = 0
|
||||
i = 1
|
||||
while(i < 10)
|
||||
{
|
||||
if(i % 2 == 0)
|
||||
{
|
||||
i++
|
||||
continue
|
||||
}
|
||||
total = total + i
|
||||
i++
|
||||
}
|
||||
print "total=", total
|
||||
}'
|
||||
```
|
||||
|
||||
打印第一行的前七列
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '/^root/{i=1; while(i<=7){print $i; i++}}' /etc/passwd
|
||||
root
|
||||
x
|
||||
0
|
||||
0
|
||||
root
|
||||
/root
|
||||
/bin/bash
|
||||
```
|
||||
|
||||
分别打印每行的每列
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk '{i=1; while(i<=NF){print $i; i++}}' /etc/hosts
|
||||
127.0.0.1
|
||||
localhost
|
||||
localhost.localdomain
|
||||
localhost4
|
||||
localhost4.localdomain4
|
||||
::1
|
||||
localhost
|
||||
localhost.localdomain
|
||||
localhost6
|
||||
localhost6.localdomain6
|
||||
```
|
||||
|
||||
#### 3. break 结束循环
|
||||
|
||||
break[n]:当第n次循环到来后,结束整个循环,n=0就是指本次循环
|
||||
|
||||
当计算的和大于 50 的时候使用 break 结束循环:
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
sum = 0; for (i = 0; i < 20; ++i) {
|
||||
sum += i; if (sum > 50) break; else print "Sum =", sum
|
||||
}
|
||||
}'
|
||||
|
||||
Sum = 0
|
||||
Sum = 1
|
||||
Sum = 3
|
||||
Sum = 6
|
||||
Sum = 10
|
||||
Sum = 15
|
||||
Sum = 21
|
||||
Sum = 28
|
||||
Sum = 36
|
||||
Sum = 45
|
||||
```
|
||||
|
||||
#### 4. continue 跳出本次循环
|
||||
|
||||
Continue 语句用于在循环体内部结束本次循环,从而直接进入下一次循环迭代。
|
||||
|
||||
Continue[n]:满足条件后,直接进行第n次循环,本次循环不在进行,n=0也就是提前结束本次循环而直接进入下一轮
|
||||
|
||||
输出 1 到 20 之间的偶数:
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {for (i = 1; i <= 20; ++i) {if (i % 2 == 0) print i ; else continue} }'
|
||||
2
|
||||
4
|
||||
6
|
||||
8
|
||||
10
|
||||
12
|
||||
14
|
||||
16
|
||||
18
|
||||
20
|
||||
```
|
||||
|
||||
#### 5. exit 结束脚本程序
|
||||
|
||||
Exit 用于结束脚本程序的执行。
|
||||
|
||||
该函数接受一个整数作为参数表示 AWK 进程结束状态。 如果没有提供该参数,其默认状态为 0。
|
||||
|
||||
当和大于 50 时结束 AWK 程序。
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk 'BEGIN {
|
||||
sum = 0; for (i = 0; i < 20; ++i) {
|
||||
sum += i; if (sum > 50) exit(10); else print "Sum =", sum
|
||||
}
|
||||
}'
|
||||
|
||||
Sum = 0
|
||||
Sum = 1
|
||||
Sum = 3
|
||||
Sum = 6
|
||||
Sum = 10
|
||||
Sum = 15
|
||||
Sum = 21
|
||||
Sum = 28
|
||||
Sum = 36
|
||||
Sum = 45
|
||||
```
|
||||
|
||||
检查脚本执行后的返回状态
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# echo $?
|
||||
10
|
||||
```
|
||||
|
||||
#### 6. next 停止处理
|
||||
|
||||
next:提前结束对本行的处理动作而直接进入下一行处理
|
||||
|
||||
```bash
|
||||
[root@wxin ~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user