一、sed
sed是一种新型的,非交互式的流编辑器,它能执行与编辑器 vi 和 ex 相同的编辑任务。sed 编辑器没有提供交互式使用方式,使用者只能在命令行输入编辑命令、指定文件名,然后在屏幕上查看输出。
工作原理:
sed 编辑器逐行处理文件(或输入),并将输出结果发送到屏幕。 sed 把当前正在处理的行保存在一个临时缓存区中,这个缓存区称为“模式空间”或“临时缓冲”。sed 处理完模式空间中的行后(即在该行上执行sed 命令后),就把改行发送到屏幕上(除非之前有命令删除这一行或取消打印操作),执行下一个循环。 sed 每处理完输入文件的最后一行后, sed 便结束运行。 sed 把每一行都存在模式空间中,对这个副本进行编辑,所以不会修改或破坏原文件
它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。
如果没有使诸如‘D’的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出或者-i进行修改。
功能:
主要用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等;对文本按行处理
用法:
sed [选项]... '地址界定 处理动作' 文件...
或
前置命令 | sed [选项] '地址界定 处理动作’
常用选项:
- -n:不输出模式空间内容到屏幕,即不自动打印
- -e: 多点编辑
- -f /PATH/SCRIPT_FILE: 从指定文件中读取编辑脚本 这里的编辑脚本每行一个不需要带引号
- -r: 支持使用扩展正则表达式 regexp-extended
- -i:直接将处理的结果写入文件
正常情况下,sed命令所做的处理只是把操作结果(包括打印、删除等)输出到当前终端屏幕,而并不
会对原始文件做任何更改。若希望直接修改文件内容,应添加选项 -i 。为了避免生产环境中因误操作导
致系统故障,使用时要谨慎
script:地址定界编辑命令
- 地址定界:
(1)空地址:对全文进行处理
(2)单地址:
# :指定第#行
/pattern/ :被此模式所匹配到的每一行
(3)地址范围:
num1,num2 :从第num1行到num2行
num3,+num :从第num3行开始后的共num行的所有行(包括第num3行)
num4,/pattern1/ :从第num4行到模式1匹配到的行的所有行
/pattern2/,/pattern3/ :从模式2匹配到的内容行直到模式3匹配到的内容行的所有行
$ :最后一行;
(4) 步进:~
1~2:所有奇数行
2~2:所有偶数行
- 处理动作(编辑命令):
d :删除;
p :显示模式空间中的内容;
a \text :在行后面追加文本“text”,支持使用\n实现多行追加;
i \text :在行前面插入文本“text”,支持使用\n实现多行插入;
c \text :把匹配到的行替换为此处指定的文本“text”;
w /PATH/TO/SOMEFILE :保存模式空间匹配到的行至指定的文件中;
r /PATH/FROM/SOMEFILE :读取指定文件的内容至当前文件被模式匹配到的行后面;文件合并;
= :为模式匹配到的行打印行号;
! :条件取反;
s/old/new/替换标记 :查找替换,将指定范围内的old字符串替换成old字符串。其分隔符可自行指定,常用的有s@@@, s###等;
s/old/new/ :将每行匹配到的第一个old替换为new
s/old/new/NUM :将每行匹配到的第NUM个old替换成new
s/old/new/g :将所有的old替换成 new
替换标记:
g :全局替换;
w /PATH/TO/SOMEFILE :将替换成功的结果保存至指定文件中;
p :显示替换成功的行;
NUMg :替换每一行指定第NUM个以及NUM个以后
综述:地址界定即为address-range1|pattern-range1 [address-range2|pattern-range2]
- address-range
- address-range1,address-range2
- address-range,pattern-range
- pattern-range
- pattern-range1,pattern-range2
- pattern-range,address-range
1.模式匹配(正则)
[root@eddy ~]# sed -n '/^root.*bash$/ p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
2.打印/etc/passwd文件所有内容
sed -n 'p' /etc/passwd
3.将root替换成tree并输出
[root@eddy ~]# sed -n 's/root/tree/ p' /etc/passwd
tree:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/tree:/sbin/nologin
4.多点编辑
[root@eddy ~]# sed -n -e '/^root/ p' -e '/^apache/ p' /etc/passwd
5.打印第1行内容
[root@eddy ~]# sed -n '1 p' /etc/passwd
6.打印第10行至最后一行的内容
[root@eddy ~]# sed -n '10,$ p' /etc/passwd
7.打印第3行至所匹配内容行之间的内容(左右均为闭区间)
[root@eddy ~]# sed -n '3,/root/ p' passwd
如果直至文件最后都未匹配到root,那么便会输出第3行至文件最后一行的所有内容
sed -n '/pattern/,NUM p' FILENAME
- 如果pattern模式未匹配到内容,将不会有任何输出
- 如果pattern匹配到的行的行号大于NUM,那么只会输出pattern所匹配到的行
- 如果pattern匹配到的行的行号小于NUM,那么便会输出pattern匹配到的行至NUM行的所有行
8.在匹配到的行或第NUM行前插入指定内容:
[root@eddy ~]# sed '/pattern/ i 插入内容' 文件名
或
[root@eddy ~]# sed 'NUM i 插入内容' 文件名
9.将匹配到的行或第NUM行的内容进行重新指定:
[root@eddy ~]# sed '/pattern/ c 修改后的内容' 文件名
或
[root@eddy ~]# sed 'NUM c 修改后的内容' 文件名
10.打印出文件中有指定范围中的某个字段:
[root@eddy ~]# sed -n '/内容1\|内容2/p' 文件名
11.打印第NUM1行至NUM2行的所有内容:
[root@eddy ~]# sed -n 'NUM1,NUM2 p' 文件名
12.打印从第NUM行开始步长为STEP的行的内容:
sed -n 'NUM~STEP' 文件名
13.从指定的脚本文件中读取对文本的处理动作(编辑脚本中每行一条且不需要带引号)
sed -n -f 脚本名 文件名
eg:
[root@eddy ~]# cat script.sed
/^root/ p
/^apache/ p
[root@eddy ~]# sed -n -f script.sed /etc/passwd
root:x:0:0:root:/root:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
14.对地址界定进行取反(!)
sed [option] '地址界定 ! 处理动作 ' FILENAME
eg:
[root@eddy ~]# cat passwd
dxk:x:1000:1000::/home/dxk:/bin/bash
ntp:x:38:38::/etc/ntp:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
test:x:1001:1001::/home/test:/bin/bash
bob:x:1002:1002::/home/bob:/bin/bash
tcpdump:x:72:72::/:/sbin/nologin
[root@eddy ~]# sed -n '/dxk/,3 ! p' passwd
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
test:x:1001:1001::/home/test:/bin/bash
bob:x:1002:1002::/home/bob:/bin/bash
tcpdump:x:72:72::/:/sbin/nologin
15.将处理后的行写入文件
sed [选项] ‘地址界定 w filename’ FILENAME #(只将有改动的行写入文件)
16.删除第NUM行内容
sed 'NUM d' FILENAME
17.删除指定行范围内的内容
sed 'NUM1,NUM2 d' FILENAME
18.删除指定模式匹配到的内容
sed '/pattern/ d' FILENAME
sed 'NUM,/pattern/ d' FILENAME
sed '/pattern/,NUM d' FILENAME
sed '/pattern1/,/pattern2/ d' FILENAME
19.删除第NUM行(或模式匹配到的行)及以下num行
sed 'NUM,+num d' FILENAME
或
sed '/pattern/,+num d' FILENAME
注意:没有-num
20.删除空行:
sed '/^$/ d' FILENAME
21.删除注释行:
sed '/^#/ d' FILENAME
22…替换
用法:sed [选项] ‘[地址界定] s/要替换的字符串/替换后的字符串/[替换标记]’ 文件名
将FILENAME文件中的str1字符串替换成为str2
因为替换标记省略未写,所以默认是将匹配到str1行的第一个str1替换成str2,若同一行有两个str1,则只替换第一个
sed 's/str1/str2/' FILENAME
全局替换
即将所有匹配到的都进行替换,一行内无论出现多少个str1都被str2替换
sed 's/str1/str2/g' FILENAME
将替换后的所在行写入到指定文件中(文件不存在会创建)
sed -n 's/str1/str2/w filename' FILANAME
只将每行匹配到的第num个str1替换成为str2,并打印出来
sed -n '[地址界定] s/str1/str2/num p' FILENAME
将每行匹配到的第num个及该行后的所有str1替换成为str2,并打印出来
sed -n '[地址界定] s/str1/str2/numg p' FILENAME
&的使用:
[root@eddy ~]# sed -n 's/^roo./<&>/g p' /etc/passwd
<root>:x:0:0:root:/root:/bin/bash
[root@eddy ~]# echo "This Is a Test.." |sed 's/\([A-Z]\)/(&)/g'
(T)his (I)s a (T)est..
[root@eddy ~]# echo "This Is a Test.." |sed 's/\([A-Z]\)/\(\1\)/g'
(T)his (I)s a (T)est..
取出/etc/passwd中的所有用户
sed 's/\([^:]*\).*/\1/' /etc/passwd
所有的两位数结尾的行后面都加上 .1
sed 's/[0-9][0-9]$/&.1/' FILENAME
紧跟在 s 命令后的字符就是查找串和替换串之间的分隔符。分隔符默认为正斜杠,但可以改变。无论什么字符(换行符,反斜线除外),只要紧跟在 s 命令,就成了新的串分隔符。这个方法在查找包含正斜杠模式时很管用,例如查找路径名或日期
sed [option] '[地址定界] s#str1#str2#替换标记' FILANAME
sed [option] '[地址定界] s@str1@str2@替换标记' FILENAME
sed [option] '[地址定界] s/str1/str2/替换标记' FILENAME
18.读写入文件
在FILENAME文件的第num行后插入filename文件的内容
sed 'num r filename' FILENAME
在FILENAME文件的第num1行和num2行后均插入filename文件的内容
sed 'num1,num2 r filename' FILENAME
将匹配到的文本内容存为另一个文件
sed -n '地址界定 w filename' FILENAME
在匹配到的行的行前插入内容:
sed [选项] '地址界定 i 插入内容' FILENAME
在匹配到的行的行后插入内容:
sed [选项] '地址界定 a 插入内容' FILENAME
将匹配到的行替换为指定内容:
sed [选项] '地址界定 c 替换内容' FILENAME
19.使用sed命令打印出ifconfig ens32的ip地址
[root@eddy ~]# ifconfig ens32 | sed -nr '/\<inet\>/ s/(.*inet )(.*)(netmask.*)/\2/ p'
192.168.126.8
或
[root@eddy ~]# ifconfig ens32 | sed -n '2p' | sed -r 's/.*inet (.*)netmask.*/\1/'
192.168.126.8
20.使用sed命令打印出系统版本
[root@eddy ~]# sed -r -n 's/.*release[[:space:]]*([^.]+).*/\1/p' /etc/redhat-release
7
21.将文件中的以至少一个空白字符开头的行的行首加#
sed -n '/^ .*/ s/^/#/ p' FILENAME
或
sed 's/\(^[[:space:]]\)/#\1/g' FILENAME
22.将文件的1~5行进行注释
sed '1,5 s@^@#@' FILENAME
#要想直接对原文件进行作用并生效,需加-i选项
sed -i '1,5 s@^@#@' FILENAME
23.将/etc/yum.repos.d/CentOS-Media.repo文件中所有的enabled=0或gpgcheck=0的最后的0修改
为1
sed -i 's/enabled=0/enabled=1/g;s/gpgcheck=0/gpgcheck=1/g' /etc/yum.repos.d/CentOS-
Media.repo
保持空间和模式空间
sed 有两个内置的存储空间:在使用高级命令的时候用到
- 模式空间:模式空间用于 sed 执行的正常流程中。 该空间 sed 内置的一个缓冲区,用来存放、修改、从输入文件读取的内容。(即对文件的操作都是在模式空间中进行的)
- 保持空间:保持空间是另外一个缓冲区,用来存放临时数据。 Sed 可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。 我们已经讨论过,每次循环读取数据过程中,模式空间的内容都会被清空,然而保持空间的内容则保持不变,不会在循环中被删除。
高级编辑命令:
h:把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g:把保持空间中的内容覆盖至模式空间中;
G:把保持空间中的内容追加至模式空间中;
x:把模式空间中的内容与保持空间中的内容互换;
n:覆盖读取匹配到的行的下一行至模式空间中;
N:追加读取匹配到的行的下一行至模式空间中;
d:删除模式空间中的行;
D:删除多行模式空间中的所有行;
对文件进行倒序打印sed '1!G;h;$!d' FILENAME
例:sed ‘1!G;h;$!d’ sedH.txt 执行过程
1.打印偶数行
sed -n '2~2 p' FILENAME
或
sed -n 'n;p' FILENAME
2.打印文本文件的最后一行
sed '$!d' FILENAME
3.取出文件后两行
sed '$!N;$!D' FILENAME
4.删除原有的所有空白行,而后为所有的非空白行后添加一个空白行
sed '/^$/d;G' FILENAME
5.显示奇数行
sed 'n;d' FILENAME
6.在原有的每行后方添加一个空白行
sed 'G' FILENAME
7.把第1-3行复制到文件末尾
sed ‘1h;2,3H;$G’ FILENAME
8.把第2行复制第4行
sed '2h;4G' FILENAME
9.把第1行剪切到文件末尾
sed ‘1h,1d;$G’ FILENAME
10.把第1-2行剪切到文件末尾
sed ‘1h;2H;1,2d;$G’ FILENAME
11.显示/etc/passwd文件中位于第偶数行的用户的用户名
sed -n 'n;p' /etc/passwd | cut -d: -f 1
sed -n '2~2p' /etc/passwd | cut -d: -f 1
sed -n 'n; s/:.*//p' /etc/passwd
sed -n '2~2 s/:.*//p' /etc/passwd
sed -nr 'n; s/(^[^:]+).*/\1/p ' /etc/passwd
sed -nr '2~2 s/(^[^:]+).*/\1/p ' /etc/passwd
二、awk
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理
awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用
awk的处理文本和数据时:它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。
AWK 工作流程可分为三个部分:
- 读输入文件之前执行的代码段(由BEGIN关键字标识)。
- 主循环执行输入文件的代码段。
- 读输入文件之后的代码段(由END关键字标识)。
1、通过关键字 BEGIN 执行 BEGIN 块的内容,即 BEGIN 后花括号 {} 的内容。
2、完成 BEGIN 块的执行,开始执行body块。
3、读入有 \n 换行符分割的记录。
4、将记录按指定的域分隔符划分域,填充域,$0 则表示所有域(即一行内容),$1 表示第一个域,$n 表示第 n 个域。
5、依次执行各 BODY 块,pattern 部分匹配该行内容成功后,才会执行 awk-commands 的内容。
6、循环读取并执行各行直到文件结束,完成body块执行。
7、开始 END 块执行,END 块可以输出最终结果。
开始块(BEGIN)
语法格式:
BEGIN {awk-commands}
开始块就是在程序启动的时候执行的代码部分,并且它在整个过程中只执行一次。
一般情况下,我们可以在开始块中初始化一些变量。
BEGIN 是 AWK 的关键字,因此它必须是大写的。
注意:开始块部分是可选的,程序可以没有开始块部分。
主体块(BODY)
语法格式:
/pattern/ {awk-commands}
对于每一个输入的行都会执行一次主体部分的命令。
默认情况下,对于输入的每一行,AWK 都会执行命令。但是,我们可以将其限定在指定的模式中。
注意:BODY区域没有用任何关键字表示,只有用正则模式和命令。
结束块(END)
语法格式:
END {awk-commands}
结束块是在程序结束时执行的代码。 END 也是 AWK 的关键字,它也必须大写。 与开始块相似,结束块也是可选的。
用法:
1、第一种,命令行方式:
awk -F ‘/pattern/ {action}’ input-file
- -F 为字段分界符。如果不指定,默认会使用空格或制表符作为分界符。但如果处理类似passwd文件,此文件各域使用冒号作为分隔符,则必须使用-F选项: awk -F :
- /pattern/和{action}需要用单引号引起来。
- /pattern/是可选的。如果不指定, awk 将处理输入文件中的所有行。如果指定一个模式, awk
则只处理匹配指定的模式的行 - {action} 为 awk 命令,可以是单个命令,也可以多个命令。整个 action(包括里面的所有命令)都
必须放在{ 和 }之间。 - input-file 即为要处理的文件
2、第二种,将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它
3、第三种,将所有awk命令插入一个单独文件,然后调用,如:
awk -f awkscript-file input-file
-f 选项指明在文件 awkscript-file 的 awk 脚本,input-file 是使用 awk 进行浏览的文件名
模式和动作
任何awk语句都是由模式和动作组成,在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。动作即对数据进行的操作,如果省去模式部分,动作将时刻保持执行状态
模式可以是任何条件语句或复合语句或正则表达式,模式包含两个特殊字段BEGIN和END,使用BEGIN语句设置计数和打印头,BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行;END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志,有动作必须使用{}括起来
实际动作在大括号{}内指明,常用来做打印动作,但是还有更长的代码如if和for循环语句等,如果不指明采取什么动作,awk默认打印出所有浏览出的记录
域和记录
awk执行时,其浏览标记为$1,$2…$n,这种方法称为域标记。使用$1,$3表示参照第1和第3域,注意这里使用逗号分隔域,使用$0表示使用所有域。
条件操作符:
操作符 | 含义 |
---|---|
~ !~ | 匹配正则表达式 不匹配正则表达式 |
== != < <= > >= | 关系运算符 |
= += -= *= /= %= ^= **= | 赋值 |
| | 或运算 |
|| | 逻辑或 |
& | 与运算 |
&& | 逻辑与 |
++ -- | 增加或减少,作为前缀或后缀 |
$ | 字段引用 |
in | 数组成员 |
awk内置变量
变量 | 含义 |
---|---|
$n | 当前记录的第n个字段,字段间由 FS分隔。 |
$0 | 当前记录的内容 |
ARGC | 命令行参数个数 |
ARGV | 命令行参数排列 |
ENVIRON | 支持队列中系统环境变量的使用 |
FILENAME | awk浏览的文件名 |
FNR | 浏览文件的记录数 |
FS | 设置输入域分隔符,等价于命令行 -F选项 |
NF | 浏览记录的域的个数 |
NR | 已读的记录数 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 |
RS | 控制记录分隔符 |
字符串常量
字符串常量 | 描述 |
---|---|
\ | 反斜线 |
\a | alert字符,通常为ASCII BEL字符 |
\b | 退格键 |
\f | 换页 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\xhex digits | 字符由十六进制数字下面的\x中的字符串来表示 |
\c | 字面字符c |
awk命令行选项
- -v :参数传递,定义和引用变量 ,可以把外部变量引入到内部
- -f :指定脚本
- -F :指定分隔符
- -V :查看awk的版本号
print函数和printf函数
awk中同时提供了print和printf两种打印输出的函数。
其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格
print格式: print item1, item2, …
#输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式
printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂
printf:格式化输出: printf “FORMAT” , item1, item2, …
必须指定FORMAT
不会自动换行,需要显式给出换行控制符, \n
FORMAT中需要分别为后面每个item指定格式符
printf 格式符:与item一一对应
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%: 显示%自身
printf 修饰符:
[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度, %3.1f
-:左对齐(默认右对齐) %-15s
+:显示数值的正负符号 %+d
1.显示最近登录的5个帐号
[root@eddy ~]# last -n 3 | awk '{print $1}'
root
root
reboot
当读入有’\n’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 “[tab]键”,所以$1表示登录用户,$3表示登录用户ip,以此类推
2.显示所有用户名
awk -F : '{print $1}' /etc/passwd
3.显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以制表符分割,同时打印记录号
awk -F : '{print NR, $1"\t"$NF}' /etc/passwd
4.显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"nginx,/sbin/nologin"
awk -F : 'BEGIN{print"USER,BASH"}{print $1","$NF}END{print"nginx,/sbin/nologin"}' /etc/passwd
先执行BEGING操作,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作
5.搜索/etc/passwd有root关键字的所有行
awk -F : '/root/' /etc/passwd
pattern的使用示例,匹配了pattern的行才会执行action(没有指定action,默认输出每行的内容)。搜索支持正则搜索/etc/passwd有root关键字的所有行,并显示对应的shell
6.内置变量NF( 浏览记录的域的个数)
awk -F : '/root/ {print $NF}' /etc/passwd
这里指定action为{print $NF}
7.统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容
awk -F : '{print "filename:"FILENAME,"rownumber:"NR,"columns:"NF",content:"$0}' /etc/passwd
8.使用printf替代print,可以让代码更加简洁,易读
awk -F : '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
9.FNR:表示浏览文件的记录数;NR:表示已读的记录数
awk -F: '{print FNR, $0}' /etc/passwd /etc/hosts
awk -F: '{print NR, $0}' /etc/passwd /etc/hosts
每行的列数可用NF即{print NF},那么每行的最后一个域的字段值便可用{print $NF}查看;行号可用NR,即{print NR};FNR表示浏览文件的记录数
10.自定义分隔符
awk -F '[ :\t]' '{print $1,$2,$3}' /etc/passwd #指定分隔符为冒号,空格或制表符
#等价于:
awk 'BEGIN{FS="[ :\t]"} {print $1,$2,$3}' /etc/passwd
11.OFS:表示输出域分隔符;ORS:表示输出记录分隔符
#自定义输出域分隔符
awk 'BEGIN{FS=":"; OFS="@@"} /^root/{print $1,$2,$3,$4}' /etc/passwd
#自定义输出记录分隔符
awk 'BEGIN{FS=":"; ORS="++"} {print $0}' /etc/passwd
12.多条件搜索
awk -F: '/^root|bash$/' /etc/passwd
13.输出使用量小于500M的文件系统、可用量和其所挂载点
df | awk '$4 < 512000 {print $1,$(NF-2),$NF}'
14.printf函数的格式化输出
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
- %s表示以字符串格式显示;-表示左对齐;20表示显示宽度
- %d表示以十进制整数格式显示;10表示显示宽度;不加-号默认为右对齐
- \n表示换行
15.格式化显示系统中的用户和其UID
awk -F: '{printf "Username: %-15s UID:%d\n",$1,$3}' /etc/passwd
16.非精确匹配
awk '$n ~ /pattern/ {action}' FILENAME
awk '$n ~ /(pattern1 | pattern2)/ {action}' FILENAME
17.精确匹配
awk '$n==“str” {action}' FILENAME
18.不匹配
awk '$n !~ /pattern/ {action}' FILENAME
awk '$n != “str” {action}' FILENAME
19.打印出/etc/passwd 第一个域,并且在第一个域所有的内容前面加上“用户帐号:
cat /etc/passwd |awk -F: '{print"用户帐号:"$1}'
20.匹配/etc/passwd 第三域大于100的显示出完整信息
awk -F: '{if($3>100) print$0}' /etc/passwd
21.匹配/etc/passwd行号小于15的,并且最后一域匹配bash的信息
awk -F : '{if(NR<15 && $NF~/bash/) print $0}' /etc/passwd
22.匹配/etc/passwd第一域匹配daemon的信息
awk -F: '$1=="daemon"' /etc/passwd
23.打印出/etc/passwd文件中的第三域数字之和
awk -F: '{sum=sum+$3}END{print sum}' /etc/passwd
24.匹配passwd文件最后一段域bash结尾的信息,有多少条
awk -F: '($NF~/bash/){print NR}' /etc/passwd |wc -l
awk -F: '{if($NF~/bash/) print $0}' /etc/passwd | wc -l
awk -F: '/bash$/{array[$7]++} END{for (i in array) print i,array[i]}' /etc/passwd
awk -F: '$NF~/bash/ {array[$7]++} END{for (i in array) print i,array[i]}' /etc/passwd
25.同时匹配passwd文件中,带mail和bash的关键字的信息
awk -F: '/root|mail/' /etc/passwd
awk -F: '$0~/root|mail/' /etc/passwd
awk -F: '{if($0~/mail/ || $0~/root/) print $0}' /etc/passwd
26.统计访问本服务器网站的IP地址及次数
awk '{print $1}' /var/log/httpd/access_log | sort -n | uniq -c | sort -nrk 1
awk '{array[$1]++}END{for (i in array) print i,array[i]}' /var/log/httpd/access_log | sort -nrk 2
27.统计/etc/fstab 文件中每个文件系统类型出现的次数
awk '$1!~/#/ && $0!~/^$/ {array[$3]++}END{for (i in array) print i,array[i] }' /etc/fstab
28.统计文件中每个域字段的内容以及出现的次数
awk '{for (i=1;i<=NF;i++) array[$i]++}END{for (j in array) print j,array[j]}' FILENAME
29.统计/etc/fstab 文件中每个单词出现的次数
awk -F [/\ [:punct:]]+ '{for (i=1;i<NF;i++){if ($i!~/[0-9]+/ && $i!=""){array[$i]++}}}END{for (j in array) print j,array[j]}' /etc/fstab
30.提取字符串"Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"中的所有数字
echo "Yd$C@M05MB%9&B9dh7dq+YVi9xp3vp7w"|awk -F "[^0-9]+" '{for (i=1;i<=NF;i++){if ($i!="") {print $i}}}'
echo "Yd$C@M05MB%9&B9dh7dq+YVi9xp3vp7w"|awk -F "[^[:digit:]]" '{for (i=1;i<=NF;i++){if ($i!="") {print $i}}}'
31.统计netstat -tan 中各状态的次数
netstat -tan|awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}'
32.统计出/etc/passwd文件中shell的种类和个数
awk -F: '{shell[$NF]++}END{for (i in shell){print i,shell[i]}}' /etc/passwd
33.计算/etc/passwd中所有用户的UID平均数,以及GID平均数
awk -F: '{U+=$3;G+=$4}END{print "U_avg:"U/NR"\nG_avg:"G/NR}' /etc/passwd
34.使用:符号做分隔符,将字段逆序输出/etc/passwd文件的每行
awk -F: '{for(i=NF;i>1;i--)printf "%s:",$i;print $i}' /etc/passwd
35.统计当前目录下的文件占用的总字节数
ls -l | awk 'BEGIN {SIZE=0;}{SIZE=SIZE+$5} END{print "size is",SIZE}'
36.统计ps中VSZ,RSS各自总和
ps aux | awk 'BEGIN{print "ps MEM statistic"}{V+=$5;R+=$6}END{print "VSZ_SUM: "V/1024"M\n""RSS_SUM:"R/1024"M"}'
37.根据uid值给用户分等级 Admin system users输出格式:
LEVEL NAME
Admin root
sysuser bin
users seke
[root@eddy ~]# cat level.awk
BEGIN{
print "LEVEL\t\tNAME"
}
{if($3==0){
a++;print"admin\t\t"$1"\n"
}
else if($3<500){
s++;print "sysuser\t\t"$1"\n"
}
else{
u++;print "user\t\t"$1"\n"
}
}
END{
print "admin:"a,"sysuser:"s,"user:"u
}
[root@eddy ~]# awk -F : -f level.awk /etc/passwd
38.统计/etc/passwd的账户人数
awk 'BENGIN {count=0;}{count+=1} END{print "user count is ", count}' /etc/passwd
39.打印九九乘法表 (取1-9使用 seq 9)
seq 9 | sed 'H;g'| awk -v RS='' '{for(i=1;i<=NF;i++) printf("%d*%d=%d%s",i,NR,i*NR,i==NF?"\n":"\t")}'