概述
awk、grep、sed三者的功能都是处理文本,但侧重点各不相同,其中grep适合单纯的查找或匹配文本;sed适合编辑匹配到的文本;awk功能最强大,但也最复杂,它适合格式化文本,对文本进行较复杂格式处理。
简单概括:
grep:数据查找定位
sed:数据修改
awk:数据切片
一、grep命令
grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。grep命令是Linux系统中一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
补充说明:grep 指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设grep指令会把含有范本样式的那一列显示出来。若不指定任何文件名称,或是所给予的文件名为“-”,则grep指令会从标准输入设备读取数据。
1.格式
grep [options]
**语法**:grep\
[-abcEFGhHilLnqrsvVwxy] \
[-A<显示列数>] \
[-B<显示列数>] \
[-C<显示列数>] \
[-d<进行动作>] \
[-e<范本样式>] \
[-f<范本文件>] \
[--help] \
[范本样式] \
[文件或目录...] \
2.主要参数
[options]主要参数:
-a 或 --text : 不要忽略二进制的数据。
-A<显示行数> 或 --after-context=<显示行数> : 除了显示符合范本样式的那一列之外,并显示该行之后的内容。
-b 或 --byte-offset : 在显示符合样式的那一行之前,标示出该行第一个字符的编号。
-B<显示行数> 或 --before-context=<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前的内容。
-c 或 --count : 计算符合样式的列数。
-C<显示行数> 或 --context=<显示行数>或-<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前后的内容。
-d <动作> 或 --directories=<动作> : 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
-e<范本样式> 或 --regexp=<范本样式> : 指定字符串做为查找文件内容的样式。
-E 或 --extended-regexp : 将样式为延伸的正则表达式来使用。
-f<规则文件> 或 --file=<规则文件> : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。
-F 或 --fixed-regexp : 将样式视为固定字符串的列表。
-G 或 --basic-regexp : 将样式视为普通的表示法来使用。
-h 或 --no-filename : 在显示符合样式的那一行之前,不标示该行所属的文件名称。
-H 或 --with-filename : 在显示符合样式的那一行之前,表示该行所属的文件名称。
-i 或 --ignore-case : 忽略字符大小写的差别。
-l 或 --file-with-matches : 列出文件内容符合指定的样式的文件名称。
-L 或 --files-without-match : 列出文件内容不符合指定的样式的文件名称。
-n 或 --line-number : 在显示符合样式的那一行之前,标示出该行的列数编号。
-o 或 --only-matching : 只显示匹配PATTERN 部分。
-q 或 --quiet或--silent : 不显示任何信息。
-r 或 --recursive : 此参数的效果和指定"-d recurse"参数相同。
-s 或 --no-messages : 不显示错误信息。
-v 或 --invert-match : 显示不包含匹配文本的所有行。
-V 或 --version : 显示版本信息。
-w 或 --word-regexp : 只显示全字符合的列。
-x --line-regexp : 只显示全列符合的列。
-y : 此参数的效果和指定"-i"参数相同。
--help 在线帮助。
pattern正则表达式主要参数:
\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
<:从匹配正则表达式的行开始。
>:到匹配正则表达式的行结束。
[ ]:单个字符,如[A]即A符合要求。
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求。
. :所有的单个字符。
*:有字符,长度可以为0。
3.grep命令使用实例
$ grep'test' d*
显示所有以d开头的文件中包含test的行。
$ grep'test' aa bb cc
显示在aa,bb,cc文件中匹配test的行。
$ grep'[a-z]\{5\}' aa
显示所有包含每个字符串至少有5个连续小写字符的字符串的行。
$ grep'w\(es\)t.*\1' aa
如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着 另外一个es(\1),找到就显示该行。
如果用egrep或grep -E,就不用”\”号进行转义,直接写成’w(es)t.*\1′就可以了。
假设您正在’/usr/src/Linux/Doc’目录下搜索带字符 串’magic’的文件:
$ grep magic /usr/src/Linux/Doc/*
sysrq.txt:* How do I enable the magic SysRQ key?
sysrq.txt:* How do I use the magic SysRQ key?
其中文件’sysrp.txt’包含该字符串,讨论的是 SysRQ 的功能。
默认情况下,’grep’只搜索当前目录。如果 此目录下有许多子目录,’grep’会以如下形式列出:
grep: sound: Is a directory
这可能会使’grep’ 的输出难于阅读。这里有两种解决的办法:
明确要求搜索子目录:grep -r
或忽略子目录:grep -d skip
如果有很多 输出时,您可以通过管道将其转到’less’上阅读:
$ grep magic /usr/src/Linux/Documentation/* | less
这样,您就可以更方便地阅读。
有一点要注意,您必需提供一个文件过滤方式(搜索全部文件的话用 *)。如果您忘了,’grep’会一直等着,直到该程序被中断。如果您遇到了这样的情况,按 <CTRL c> ,然后再试。
下面还有一些有意思的命令行参数:
grep -i pattern files :不区分大小写地搜索。默认情况区分大小写,
grep -l pattern files :只列出匹配的文件名,
grep -L pattern files :列出不匹配的文件名,
grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’),
grep -C number pattern files :匹配的上下文分别显示[number]行,
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。
grep -n pattern files 即可显示行号信息
grep -c pattern files 即可查找总行数
这里还有些用于搜索的特殊符号:
\< 和 \> 分别标注单词的开始与结尾。
例如:
grep man * 会匹配 ‘Batman’、’manic’、’man’等,
grep ‘\<man’ * 匹配’manic’和’man’,但不是’Batman’,
grep ‘\<man\>’ 只匹配’man’,而不是’Batman’或’manic’等其他的字符串。
‘^’:指匹配的字符串在行首,
‘$’:指匹配的字符串在行 尾,
二、sed命令
sed是Linux下一款功能强大的非交互流式文本编辑器,可以对文本文件进行增、删、改、查等操作,支持按行、按字段、按正则匹配文本内容,灵活方便,特别适合于大文件的编辑。sed在处理文本时是逐行读取文件内容,读到匹配的行就根据指令做操作,不匹配就跳过。
sed的使用方法,调用sed 命令的语法有两种:
在命令行指定sed指令对文本进行处理:sed +选项 ‘指令’ 文件
先将sed指令保存到文件中,将该文件作为参数进行调用:sed +选项 -f 包含sed指令的文件 文件
1.命令格式
sed [options] 'command' file(s);
sed [options] -f scriptfile file(s);
语法
sed [-hnV][-e<script>][-f<script文件>][文本文件]
2.参数命令
参数选项:
-e :直接在命令行模式上进行sed动作编辑,此为默认选项;
-f :将sed的动作写在一个文件内,用–f filename 执行filename内的sed动作;
-i :直接修改文件内容;
-n :只打印模式匹配的行;
-r :支持扩展表达式;
-h或--help:显示帮助;
-V或--version:显示版本信息。
编辑动作命令:
a 在当前行下面插入文本;
i 在当前行上面插入文本;
c 把选定的行改为新的文本;
d 删除,删除选择的行;
D 删除模板块的第一行;
s 替换指定字符;
h 拷贝模板块的内容到内存中的缓冲区;
H 追加模板块的内容到内存中的缓冲区;
g 获得内存缓冲区的内容,并替代当前模板块中的文本;
G 获得内存缓冲区的内容,并追加到当前模板块文本的后面;
l 列表不能打印字符的清单;
n 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令;
N 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码;
p 打印模板块的行。 P(大写) 打印模板块的第一行;
q 退出Sed;
b lable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾;
r file 从file中读行;
t label if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾;
T label 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾;
w file 写并追加模板块到file末尾;
W file 写并追加模板块的第一行到file末尾;
! 表示后面的命令对所有没有被选定的行发生作用;
= 打印当前行号;
# 把注释扩展到下一个换行符以前;
使用正则表达式、扩展正则表达式(必须结合-r选项)
替换标记
g 表示行内全面替换;
p 表示打印行;
w 表示把行写入一个文件;
x 表示互换模板块中的文本和缓冲区中的文本;
y 表示把一个字符翻译为另外的字符(但是不用于正则表达式);
\1 子串匹配标记;
& 已匹配字符串标记;
元字符集
^ 匹配行开始,如:/^sed/匹配所有以sed开头的行;
$ 匹配行结束,如:/sed$/匹配所有以sed结尾的行;
. 匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d;
匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行;
[] 匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed;
[^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行;
(..) 匹配子串,保存匹配的字符,如s/(love)able/\1rs,loveable被替换成lovers;
& 保存搜索字符用来替换其他字符,如s/love/&/,love这成love;
< 匹配单词的开始,如:/\
> 匹配单词的结束,如/love>/匹配包含以love结尾的单词的行;
<pattern> 单词锚点
x{m} 重复字符x,m次,如:/0{5}/匹配包含5个0的行;
x{m,} 重复字符x,至少m次,如:/0{5,}/匹配至少有5个0的行;
x{m,n} 重复字符x,至少m次,不多于n次,如:/0{5,10}/匹配5~10个0的行;
^$ 空白行
\?匹配紧挨在前面的字符0次或1次
[:digit:] 所有数字, 相当于0-9, [0-9]---> [[:digit:]]
[:lower:] 所有的小写字母
[:upper:] 所有的大写字母
[:alpha:] 所有的字母
[:alnum:] 相当于0-9a-zA-Z
[:space:] 空白字符
[:punct:] 所有标点符号
3.sed命令使用实例
打印文件中的行
-n选项和p命令一起使用表示只打印那些发生替换的行
sed -n '3p'1.txt #打印文件中的第三行内容
sed -n '2~2p'1.txt #从第二行开始,每隔两行打印一行,波浪号后面的2表示步长
sed -n '$p'1.txt #打印文件的最后一行
sed -n '1,3p'1.txt #打印1到3行
sed -n '3,$p'1.txt #打印从第3行到最后一行的内容
sed -n '/you/p'1.txt #逐行读取文件,打印匹配you的行
sed -n '/bob/,3p'1.txt #逐行读取文件,打印从匹配bob的行到第3行的内容
sed -n '/you/,3p'1.txt #打印匹配you 的行到第3行,也打印后面所有匹配you 的行
sed -n '1,/too/p'1.txt #打印第一行到匹配too的行
sed -n '3,/you/p'1.txt #只打印第三行到匹配you的行
sed -n '/too/,$p'1.txt #打印从匹配too的行到最后一行的内容
sed -n '/too/,+1p'1.txt #打印匹配too的行及其向后一行,如果有多行匹配too,则匹配的每一行都会向后多打印一行
sed -n '/bob/,/too/p'1.txt #打印从匹配内容bob到匹配内容too的行
打印文件的行号
sed -n "$="1.txt #打印1.txt文件最后一行的行号(即文件有多少行,和wc -l 功能类似)
sed -n '/error/='1.txt #打印匹配error的行的行号
sed -n '/error/{=;p}'1.txt #打印匹配error的行的行号和内容(可用于查看日志中有error的行及其内容)
拼接数字,中间用,连接
# 第一行行首再添加(sed -i '1{s/^/(/}' a.txt
# 每行行尾添加,
sed -i 's/$/,/' a.txt
# 最后一行去除,
sed -i '${s/\,//}' a.txt
# 最后一行行尾添加)
sed -i '${s/$/)/}' a.txt
# 合并行
sed -i ':l;N;s/\n//;b l;' a.txt
拼接字符,中间用,连接
# 每行行首行尾添加',第一行行首再添加(;sed -i "s/^/'/;s/$/',/;1{s/^/(/}" a.txt
# 最后一行去除,
sed -i '${s/\,//}' a.txt
# 最后一行行尾添加)
sed -i '${s/$/)/}' a.txt
# 合并行
sed -i ':l;N;s/\n//;b l;' a.txt
向文件中添加或插入行
sed'3ahello'1.txt #向第三行后面添加hello,3表示行号
sed '/123/ahello'1.txt #向内容123后面添加hello,如果文件中有多行包括123,则每一行后面都会添加
sed '$ahello'1.txt #在最后一行添加hello
sed '3ihello'1.txt #在第三行之前插入hello
sed '/123/ihello'1.txt #在包含123的行之前插入hello,如果有多行包含123,则包含123的每一行之前都会插入hello
sed '$ihello'1.txt #在最后一行之前插入hello
更改文件中指定的行
sed'1chello'1.txt #将文件1.txt的第一行替换为hello
sed '/123/chello'1.txt #将包含123的行替换为hello
sed '$chello'1.txt #将最后一行替换为hello
删除文件中的行
sed'/^\s*$/d' file #只删除纯空行
sed '/^[ ]*$/d' file #删除纯空行和由空格组成的空行
sed '4d'1.txt #删除第四行
sed '1~2d'1.txt #从第一行开始删除,每隔2行就删掉一行,即删除奇数行
sed '1,2d'1.txt #删除1~2行
sed '1,2!d'1.txt #删除1~2之外的所有行
sed '$d'1.txt #删除最后一行
sed '/123/d'1.txt #删除匹配123的行
sed '/123/,$d'1.txt #删除从匹配123的行到最后一行
sed '/123/,+1d'1.txt #删除匹配123的行及其后面一行
sed '/^$/d'1.txt #删除空行
sed '/123\|abc/!d'1.txt #删除不匹配123或abc的行,/123\|abc/ 表示匹配123或abc ,!表示取反
sed '1,3{/123/d}'1.txt #删除1~3行中,匹配内容123的行,1,3表示匹配1~3行,{/123/d}表示删除匹配123的行
替换文件中的内容
# sed 替换换行符
sed ':label;N;s/\n/:/;b label' filename
sed ':label;N;s/\n/:/;t label' filename
上面的两条命令可以实现将文件中的所有换行符替换为指定的字串,如命令中的冒号。命令的解释:
:label; 这是一个标签,用来实现跳转处理,名字可以随便取(label),后面的b label就是跳转指令
N; N是sed的一个处理命令,追加文本流中的下一行到模式空间进行合并处理,因此是换行符可见
s/\n/:/; s是sed的替换命令,将换行符替换为冒号
b label 或者 t label b / t 是sed的跳转命令,跳转到指定的标签处
将'2020-08-31 10:09:19'格式的日期替换为sysdate()
sed -i "s/'[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} [0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}'/sysdate\(\)/gp" mat.sql
sed 's/123/hello/'1.txt #将文件中的123替换为hello,默认只替换每行第一个123
sed 's/123/hello/g'1.txt #将文本中所有的123都替换为hello
sed 's/123/hello/2'1.txt #将每行中第二个匹配的123替换为hello
sed -n 's/123/hello/gpw 2.txt'1.txt #将每行中所有匹配的123替换为hello,并将替换后的内容写入2.txt
sed '/#/s/,.*//g'1.txt #匹配有#号的行,替换匹配行中逗号后的所有内容为空 (,.*)表示逗号后的所又内容
sed 's/..$//g'1.txt #替换每行中的最后两个字符为空,每个点代表一个字符,$表示匹配末尾(..$)表示匹配最后两个字符
sed 's/^#.*//'1.txt #将1.txt文件中以#开头的行替换为空行,即注释的行(^#)表示匹配以#开头,(.*)代表所有内容
sed 's/^#.*//;/^$/d'1.txt #先替换1.txt文件中所有注释的空行为空行,然后删除空行,替换和删除操作中间用分号隔开
sed 's/^[0-9]/(&)/'1.txt #将每一行中行首的数字加上一个小括号(^[0-9])表示行首是数字,&符号代表匹配的内容
或者 sed 's/[0−9][0−9]/(\1)/'1.txt #替换左侧特殊字符需钥转义,右侧不需要转义,\1代表匹配的内容
sed 's/$/&'haha'/'1.txt # 在1.txt文件的每一行后面加上"haha"字段
从文件中读取内容
sed'r 2.txt'1.txt #将文件2.txt中的内容,读入1.txt中,会在1.txt中的每一行后都读入2.txt的内容
sed '3r 2.txt'1.txt #在1.txt的第3行之后插入文件2.txt的内容(可用于向文件中插入内容)
sed '/245/r 2.txt'1.txt #在匹配245的行之后插入文件2.txt的内容,如果1.txt中有多行匹配456则在每一行之后都会插入
sed '$r 2.txt'1.txt #在1.txt的最后一行插入2.txt的内容
向文件中写入内容
sed -n 'w 2.txt'1.txt #将1.txt文件的内容写入2.txt文件,如果2.txt文件不存在则创建,如果2.txt存在则覆盖之前的内容
sed -n '2w 2.txt'1.txt #将文件1.txt中的第2行内容写入到文件2.txt
sed -n -e '1w 2.txt' -e '$w 2.txt'1.txt #将1.txt的第1行和最后一行内容写入2.txt
sed -n -e '1w 2.txt' -e '$w 3.txt'1.txt #将1.txt的第1行和最后一行分别写入2.txt和3.txt
sed -n '/abc\|123/w 2.txt'1.txt #将1.txt中匹配abc或123的行的内容,写入到2.txt中
sed -n '/666/,$w 2.txt'1.txt #将1.txt中从匹配666的行到最后一行的内容,写入到2.txt中
sed -n '/xyz/,+2w 2.txt'1.txt #将1.txt中从匹配xyz的行及其后2行的内容,写入到2.txt中
sed在shell脚本中的使用
实例1:替换文件中的内容
#!/bin/bashif [ $# -ne 3 ];then#判断参数个数echo"Usage: $0 old-part new-part filename"#输出脚本用法exitfi
sed -i "s#$1#$2#"$3#将 旧内容进行替换,当$1和$2中包含"/"时,替换指令中的定界符需要更换为其他符号
实例2:删除文件中的空白行
#!/bin/bash
if [ ! -f $1 ];then#判断参数是否为文件且存在echo"$0 is not a file"exitfi
sed -i "/^$/d"$1#将空白行删除
实例3:格式化文本内容
#!/bin/bash
a='s/^ *>// #定义一个变量a保存sed指令,'s/^ *>//':表示匹配以0个或多空格开头紧跟一个'>'号的行,将匹配内容替换
s/\t*// #'s/\t*//':表示匹配以0个或多个制表符开头的行,将匹配内容替换
s/^>// #'s/^>//' :表示匹配以'>'开头的行,将匹配内容替换
s/^ *//'#'s/^ *//':表示匹配以0个或多个空格开头的行,将匹配内容替换#echo $a
sed "$a"$1#对用户给定的文本文件进行格式化处理
实用脚本:批量更改当前目录中的文件后缀名:
示例1:
#!/bin/bashif [ $# -ne 2 ];then#判断用户的输入,如果参数个数不为2则打印脚本用法echo"Usage:$0 + old-file new-file"exitfifor i in *$1* #对包含用户给定参数的文件进行遍历doif [ -f $i ];then
iname=`basename $i` #获取文件名
newname=`echo$iname | sed -e "s/$1/$2/g"` #对文件名进行替换并赋值给新的变量
mv $iname$newname#对文件进行重命名fidoneexit 666
示例2:
#!/bin/bashread -p "input the old file:" old #提示用户输入要替换的文件后缀read -p "input the new file:" new
[ -z $old ] || [ -z $new ] && echo"error" && exit#判断用户是否有输入,如果没有输入怎打印error并退出for file in `ls *.$old`
doif [ -f $file ];then
newfile=${file%$old}#对文件进行去尾
mv $file${newfile}$new#文件重命名fidone
示例3:
#!/bin/bash
if [ $# -ne 2 ];then#判断位置变量的个数是是否为2echo"Usage:$0 old-file new-file"exitfifor file in `ls` #在当前目录中遍历文件doif [[ $file =~ $1$ ]];then#对用户给出的位置变量$1进行正则匹配,$1$表示匹配以变量$1的值为结尾的文件echo$file#将匹配项输出到屏幕进行确认
new=${file%$1}#对文件进行去尾处理,去掉文件后缀保留文件名,并将文件名赋给变量new
mv $file${new}$2#将匹配文件重命名为:文件名+新的后缀名fidone
三、awk命令
简介
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。
awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
使用方法
awk '{pattern + action}' {filenames}
尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。
awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。
调用awk
有三种方式调用awk
说明:
awk被设计用于数据流,能够对列和行进行操作。而sed更多的是匹配,进行替换和删除。
awk有很多内建的功能,比如数组,函数等。灵活性是awk的最大优势。
awk的结构
```
awk 'BEGIN{ print "start"} pattern { commands } END{ print "end"}' file
```
一个awk脚本通常是3部分
BEGIN语句块
能够使用模式匹配的通用语句块
END语句块
他们任何一部分都可以不出现在脚本中。脚本通常包含在双引号或者单引号内。例如:awk 'BEGIN{i=0}{i++}END{print i}' filename
awk的基本语法
awk通过FS作为每一段文本的分割符(默认空格),在命令行上可以用-F参数指定分隔符;
通过RS参数指定文本换行符(默认回车,所以是一行行取数据的),通过换行符作为分割来读取文件。这里区别于sed,sed是一行一行读取文件的。
基本流程:
BEGIN{在读取文件之前做的操作}
{读取文件时做的操作}
END{全部文件读取之后才进行的操作}
常用内置变量:
awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
ARGC:命令行参数个数
ARGV:命令行参数排列
ENVIRON:支持队列中系统环境变量的使用
FILENAME:awk浏览的文件名
FNR:浏览文件的记录数
FS:设置输入域分隔符,等价于命令行 -F选项
NF:浏览记录的域的个数
NR:已读的记录数
OFS:输出域分隔符
ORS:输出记录分隔符
RS: 控制记录分隔符
\t:制表符
\n:换行符
-F'[:#/]':同时定义三个分隔符
~:匹配,与==相比不是精确比较
!~:不匹配,不精确比较
==:等于,必须全部相等,精确比较
!=:不等于,精确比较
&&:逻辑与
||:逻辑或
+:匹配时表示1个或1个以上
/[0-9][0-9]+/:两个或两个以上数字
/[0-9][0-9]*/:一个或一个以上数字
$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。
自定义外部变量:
-v:自定义变量,接收shell的变量
awk -v host=$HOSTNAME"BEGIN{print host}"
工作原理
awk命令的工作方式如下
执行BEGIN{commands}语句块中的语句
从文件或者stdin中读取一行,然后执行pattern{commands}.迭代直到全部读取完毕
最后执行END{commands}语句块
再次提醒,他们任何一部都可以没有,而awk的功能也远不止如此.
awk的流程控制
条件:
if语句 if(expression){action1}else{action2}
例如:产生10个数seq 10,通过if语句判断是单数还是双数
seq 10 |awk '{if($0%2==0){print $0"是双数"}else{print $0"是单数"}}'
如果只需要一个if分支,可以省略前面的if,比如awk -F: '$3<-10 {print $1}' /etc/passwd
循环:
while语句:while(expression){action}
例子:使用:分割/etc/passwd,并将每一列前加上列号
awk -F: '{i=1;while(i<=NF){print i":"$i;i++ }}' /etc/passwd
for语句:
第一种方法:for(i=0;i<=10;i++){action}
例子:使用:分割/etc/passwd,并将每一列前加上列号
awk -F: '{for(i=1;i<=NF;i++){print i":"$i}}' /etc/passwd
第二种方法:for(value in array){action}
当value在array的key中,进行下面的操作。awk的数组类似python中的字典。
例子:统计/etc/passwd第7列的值及对应的个数
awk -F: '{a[$7]++}END{for(i in a)if(i!=""){print i":"a[i]}}' /etc/passwd
说明:a[$7]:将$7作为数组a的key,然后统计对应的个数;然后遍历for(i in a),判断i是否在数组a的key中;如果存在则打印a[i],a[i]为对应key的值,这里指个数。
数组:
array[1]="hello"
array["name"]="Jack"
数组类似python的字典,array[key值]="value值";key为索引,可以是数字也可以是字符串。
数组元素的删除:delete array["key"]
例子:定义了数组a的三个值,并打印结果查看
awk 'BEGIN{a[1]="hello";a[2]="word";a["name"]="meitian";for(i in a){print "key为"i":value为"a[i]}}'
数组的遍历:
for(key in arr){
printarr[key]
}
awk函数
内置函数
1.算术函数:
int(x) 返回x的整数部分的值,值不会四舍五入,只是取整.
sqrt(x) 返回x的平方根。
rand() 返回伪随机数r,其中0<=r<1,(伪随机数指返回的值都是上一次返回的同一个随机数)。
srand(x) 建立rand()新的种子数,如果没有指定就用当天的时间(使用srand()可以使得rand()返回不同的随机数)。
例子:rand()产生一个随机数,通过srand()产生新的种子数,然后再差生一个随机数
awk'BEGIN{print rand();srand();print rand()}'
2.字符串函数:
sub("old","new"):替换匹配到的第一个文本。
echo"hello world world" | awk '{sub("world","meitian");print $0}'
gsub("old","new"):开启全局替换,替换文本中所有匹配到的字符串。
echo"hello world world" | awk '{gsub("world","meitian");print $0}'
index("a","b"):返回字符串b在字符串a中开始的位置。
awk 'BEGIN{print index("hello world","world")}'
length("s"):返回字符串s的长度,当没有指定s时,返回$0的长度。
awk -F 'BEGIN{print length("hello world")}{print lenght()}' /etc/passwd
match("s","r"):如果正则表达式r在s中匹配到,则返回出现的起始位置,否则返回0。
awk 'BEGIN{print match("hello world","[wo]")}'
split(s,a,sep) 使用sep将字符串s分解到数组a中,默认sep为FS。例子:使用o做为分隔符,将"hello world"进行分割存储到数组a中。
awk 'BEGIN{printsplit("hello world",a,"o");for(i in a){print a[i]}}'
toupper(s):将所有小写字母转换成大写字母。
echo"hello world" |awk '{print toupper($0)}'
tolower(s):将所有大写字母转换成小写字母。
echo"HELLO WORLD" |awk '{print tolower($0)}'
自定义函数:
function 函数名(参数1,参数2,...){语句;return 表达式}
例子:求和
awk'function sum(a,b){total=a+b;return total}BEGIN{print sum(2,3)}'
注意:函数必须写在BEGIN{}{}END{}的花括号之外的地方,不能放在任何{}内,否则会报错`return' used outside function context
格式化输出
虽然大多数情况下awk的print语句可以完成任务,但有时我们还需要更多。使用两个函数printf()、sprintf(),将能让输出锦上添花。printf()会将格式化字符串打印到stdout,而sprintf()则返回可以赋值给变量的格式化字符串。