### 概念 - awk 是一种编程语言,对文件和数据进行处理 - 数据可以来自标准输入,一个或多个文件,或其他命令的输出 - 朱行扫描文件爱你,默认从第一行到最后一行,寻找匹配的特定模式的行 ### 语法结构 - awk 选项 '命令部分' 文件名 - 引用shell变量需要使用双引号引起 ### 常用选项介绍 - -F 定义字段分割符号,默认的分隔符是空格 - -v 定义变量并赋值 ### 命名部分说明 ![59e2e6e78b7e5d8f0b2bf74c16f74ff0.png](../../_resources/59e2e6e78b7e5d8f0b2bf74c16f74ff0.png) ### 内置变量 - $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) ### 实践 - 打印文件的每一行 ``` [sunqi@manjaro-vm shell_demo]$ awk 'NR=1,NR=5{print $0}' passwd root:x:0:0::/root:/bin/bash nobody:x:65534:65534:Kernel Overflow User:/:/usr/bin/nologin dbus:x:81:81:System Message Bus:/:/usr/bin/nologin bin:x:1:1::/:/usr/bin/nologin daemon:x:2:2::/:/usr/bin/nologin mail:x:8:12::/var/spool/mail:/usr/bin/nologin ftp:x:14:11::/srv/ftp:/usr/bin/nologin http:x:33:33::/srv/http:/usr/bin/nologin systemd-coredump:x:981:981:systemd Core Dumper:/:/usr/bin/nologin systemd-network:x:980:980:systemd Network Management:/:/usr/bin/nologin ``` - 打印第一行到第五行 ``` [sunqi@manjaro-vm shell_demo]$ awk 'NR==1,NR==5{print $0}' passwd root:x:0:0::/root:/bin/bash nobody:x:65534:65534:Kernel Overflow User:/:/usr/bin/nologin dbus:x:81:81:System Message Bus:/:/usr/bin/nologin bin:x:1:1::/:/usr/bin/nologin daemon:x:2:2::/:/usr/bin/nologin [sunqi@manjaro-vm shell_demo]$ me@me-EQ59:~/shell_demo$ awk 'NR>=3 && NR<=5 {print $0}' passwd bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync me@me-EQ59:~/shell_demo$ ``` - 打印第一行或第五行 ``` me@me-EQ59:~/shell_demo$ awk 'NR==1 || NR==5 {print $0}' passwd root:x:0:0:root:/root:/bin/bash sync:x:4:65534:sync:/bin:/bin/sync me@me-EQ59:~/shell_demo$ ``` - 打印 冒号 分割第一行,最后一行和倒数第二行 ``` me@me-EQ59:~/shell_demo$ awk -F: '{print $1, $NF, $(NF-1)}' passwd root /bin/bash /root daemon /usr/sbin/nologin /usr/sbin bin /usr/sbin/nologin /bin sys /usr/sbin/nologin /dev sync /bin/sync /bin games /usr/sbin/nologin /usr/games man /usr/sbin/nologin /var/cache/man lp /usr/sbin/nologin /var/spool/lpd mail /usr/sbin/nologin /var/mail news /usr/sbin/nologin /var/spool/news ``` - 以 冒号 分割,包含root关键字的行的第一列和最后一列 ``` me@me-EQ59:~/shell_demo$ awk -F: '/root/{print $1,$NF}' passwd root /bin/bash nm-openvpn /usr/sbin/nologin me@me-EQ59:~/shell_demo$ ``` - 自定义结果输出分隔符 ``` me@me-EQ59:~/shell_demo$ awk -F: 'BEGIN{OFS="#"}/root/{print $1,$NF}' passwd root#/bin/bash nm-openvpn#/usr/sbin/nologin me@me-EQ59:~/shell_demo$ awk -F: '/root/{print $1"###"$NF}' passwd root###/bin/bash nm-openvpn###/usr/sbin/nologin me@me-EQ59:~/shell_demo$ ``` ### 格式化输出 - print 类似echo - printf 类似 echo -n - %s 字符类型 - %d 数值类型 - %-15s 占15字符,- 表示左对齐,默认是右对齐 - printf 默认不会在行尾自动换行,加`\n` ``` me@me-EQ59:~/shell_demo$ awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' passwd root x 0 daemon x 1 bin x 2 sys x 3 sync x 4 games x 5 man x 6 lp x 7 mail x 8 news x 9 ``` ### 变量定义 - -v 变量名=变量值 - 调用变量不需要使用 $ 符号 ``` me@me-EQ59:~/shell_demo$ head -n 5 /etc/passwd > passwd me@me-EQ59:~/shell_demo$ cat passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync me@me-EQ59:~/shell_demo$ awk -v NUM=4 -F: '{ print $NUM }' passwd 0 1 2 3 65534 me@me-EQ59:~/shell_demo$ awk -v NUM=4 -F: '{ print NUM }' passwd 4 4 4 4 4 me@me-EQ59:~/shell_demo$ ``` ### begin end - begin 表示在程序开始前执行 - end 表示在所有文件处理完后执行 - 'BEGIN{开始处理之前};{处理中};END{处理结束后}' ``` me@me-EQ59:~/shell_demo$ cat passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync me@me-EQ59:~/shell_demo$ awk -v NUM=4 -F: 'BEGIN{print "user\tshell_name"};{ print $1"\t"$NF };END{print "user\tshell_name"}' passwd user shell_name root /bin/bash daemon /usr/sbin/nologin bin /usr/sbin/nologin sys /usr/sbin/nologin sync /bin/sync user shell_name me@me-EQ59:~/shell_demo$ ``` ### 实践 - 正则匹配从某一行到某一行 ![99275e98a56fc125fcba3c17489f58a4.png](../../_resources/99275e98a56fc125fcba3c17489f58a4.png) - 正则筛选行然后打印行 ![0746d379ccf516f12052987cdb69d62e.png](../../_resources/0746d379ccf516f12052987cdb69d62e.png) - 支持逻辑运算符 `&&`、 `||`和`!` ![130836e5300e6e1e037d37ee040bb7b1.png](../../_resources/130836e5300e6e1e037d37ee040bb7b1.png) ![1929245ee849038cfe1a9d5da7fc3443.png](../../_resources/1929245ee849038cfe1a9d5da7fc3443.png) ![7f95339bd98c5f0bee5868e52d28ee80.png](../../_resources/7f95339bd98c5f0bee5868e52d28ee80.png)