正则表达式
元字符
特殊字符 | 描述 |
---|---|
. | 匹配除换行符之外的任意单个字符,在awk中,也能匹配换行符 |
* | 匹配任意一个(包括零个)在它前面的字符(包括由正则表达式指定的字符) |
[…] | 匹配方括号中的字符任意一个,如果方括号中第一个字符为^,则表示否定匹配,即匹配除了换行符和方括号中列出的字符以外的所有字符。在awk中,也能匹配换行符。连字符(-)用于表示字符的范围。如果方括号内的第一个字符为右方括号(])则表示是这些字符中的一员。所有其他元字符在被指定为方括号成员时都失去元字符原来的含义 |
^ | 如果作为正则表达式的第一个字符,则表示匹配行的开始。在awk中匹配字符串的开始,即使字符串包含嵌入的换行符 |
$ | 如果作为正则表达式的最后一个字符,则表示匹配行的结尾。在awk中匹配字符串的结尾,即使字符串包含嵌入的换行符 |
\{n,m\} | 匹配前面某个范围内单个字符出现的次数(包括由正则表达式指定的字符)。\{n\}将匹配n次出现,\{n,\}至少匹配n次出现,而且\{n,m\}匹配n和m之间任意次出现 |
\ | 转义随后的特殊符号 ,将元字符转换成普通字符,或将普通字符转换成特殊含义 |
扩展元字符
特殊字符 | 描述 |
---|---|
+ | 匹配前面的正则表达式的一次或多次出现 |
? | 匹配前面的正则表达式的零次或一次出现 |
| | 指定可以匹配其前面的或后面的正则表达式 |
() | 对正则表达式分组 |
{n,m} | 匹配前面某个范围内单个字符或字符组出现的次数(包括由正则表达式指定的字符)。{n}将匹配n次出现,{n,}至少匹配n次出现,而且{n,m}匹配n和m之间任意次出现,用于POSIX的egrep和POSIX awk,而不是传统的egrep或awk |
POSIX字符类补充
- 字符类:由 [: 和 :] 包围的关键字组成的POSIX字符类
- 整合符号:整合符号是多字符的序列,表示这些字符应该被看做是一个单元,由 [, 和 .] 包围的字符组成
- 等价类:等价类列出应该看作是等价的字符集,例如e和ě,由地区化的字符元素(由 [= 和 =] 包围)组成
所有的这三种结构都必须出现在kuo号表达式的方括号中,例如[[:alpha:]!]匹配任意单个字母符号或感叹号,[[.ch.]]匹配整合元素ch。
字符类 | 匹配字符 |
---|---|
[:alnum:] | 可打印的字符(包括空白字符) |
[:alpha:] | 字母字符 |
[:blank:] | 空格和制表符 |
[:cntrl:] | 控制字符 |
[:digit:] | 数字字符 |
[:graph:] | 可打印的和可见的(非空格)字符 |
[:lower:] | 小写字符 |
[:print:] | 可打印的字符(包括空白字符) |
[:punct:] | 标点符号字符 |
[:space:] | 空白字符 |
[:upper:] | 大写字符 |
[:xdigit:] | 十六进制数字 |
使用案例
- 限制单词的搜索,可以在单词前和单词后使用字符集,如:["[{(]*book[]})"?!.,;:'s]*,其中["[{(]*表示在book单词前出现零个或单个的字符(" [ { ( ),[]})"?!.,;:'s]*表示在book单词后出现零个或单个的字符( ] } ) " ? ! . , ; : ’ s )
grep
命令格式:grep [option] pattern file
- grep的常用选项
- -V: 打印grep的版本号
- -E: 解释pattern作为扩展正则表达式,也就相当于使用egrep
- -F : 解释pattern作为固定字符串的列表,由换行符分隔,其中任何一个都要匹配,也就相当于使用fgrep
- -G: 将范本样式视为普通的表示法来使用。这是默认值。加不加都是使用grep
- 匹配控制选项
- -e : 使用pattern作为模式。可以用于指定多个搜索模式,或以连字符( - )开头的图案。指定字符串做为查找文件内容的样式
- -f : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。
- -i : 搜索时候忽略大小写
- -v: 反转匹配,选择没有被匹配到的内容
- -w:匹配整词,精确地单词,单词的两边必须是非字符符号(即不能是字母数字或下划线)
- -x:仅选择与整行完全匹配的匹配项。精确匹配整行内容(包括行首行尾那些看不到的空格内容都要完全匹配)
- -y:此参数的效果和指定“-i”参数相同
- 一般输出控制选项
- -c: 抑制正常输出;而是为每个输入文件打印匹配线的计数
- –color [= WHEN]:让关键字高亮显示,如–color=auto
- -L:列出文件内容不符合指定的范本样式的文件名称
- -l : 列出文件内容符合指定的范本样式的文件名称
- -m num:当匹配内容的行数达到num行后,grep停止搜索,并输出停止前搜索到的匹配内容
- -o: 只输出匹配的具体字符串,匹配行中其他内容不会输出
- -q:安静模式,不会有任何输出内容,查找到匹配内容会返回0,未查找到匹配内容就返回非0
- -s:不会输出查找过程中出现的任何错误消息,-q和-s选项因为与其他系统的grep有兼容问题,shell脚本应该避免使用-q和-s,并且应该将标准和错误输出重定向到/dev/null 代替
- 输出线前缀控制
- -b:输出每一个匹配行(或匹配的字符串)时在其前附加上偏移量(从文件第一个字符到该匹配内容之间的字节数)
- -H:在每一个匹配行之前加上文件名一起输出(针对于查找单个文件),当查找多个文件时默认就会输出文件名
- -h:禁止输出上的文件名的前缀。无论查找几个文件都不会在匹配内容前输出文件名
- –label = LABEL:显示实际来自标准输入的输入作为来自文件LABEL的输入。这是特别在实现zgrep等工具时非常有用,例如gzip -cd foo.gz | grep --label = foo -H的东西。看到 也是-H选项
- -n:输出匹配内容的同时输出其所在行号
- -T:初始标签确保实际行内容的第一个字符位于制表位上,以便对齐标签看起来很正常。在匹配信息和其前的附加信息之间加入tab以使格式整齐
- 上下文线控制选项
- -A num:匹配到搜索到的行以及该行下面的num行
- -B num:匹配到搜索到的行以及该行上面的num行
- -C num:匹配到搜索到的行以及上下各num行
- 文件和目录选择选项
- -a: 处理二进制文件,就像它是文本;这相当于–binary-files = text选项。不忽略二进制的数据
- –binary-files = TYPE:如果文件的前几个字节指示文件包含二进制数据,则假定该文件为类型TYPE。默认情况下,TYPE是二进制的,grep通常输出一行消息二进制文件匹配,或者如果没有匹配则没有消息。如果TYPE不匹配,grep假定二进制文件不匹配;这相当于-I选项。如果TYPE是文本,则grep处理a二进制文件,如果它是文本;这相当于-a选项。警告:grep --binary-files = text可能会输出二进制的垃圾,如果输出是一个终端和如果可能有讨厌的副作用终端驱动程序将其中的一些解释为命令
- -D:如果输入文件是设备,FIFO或套接字,请使用ACTION处理。默认情况下,读取ACTION,这意味着设备被读取,就像它们是普通文件一样。如果跳过ACTION,设备为 默默地跳过
- -d: 如果输入文件是目录,请使用ACTION处理它。默认情况下,ACTION是读的,这意味着目录被读取,就像它们是普通文件一样。如果跳过ACTION,目录将静默跳过。如果ACTION是recurse,grep将递归读取每个目录下的所有文件;这是相当于-r选项
- –exclude=GLOB:跳过基本名称与GLOB匹配的文件(使用通配符匹配)。文件名glob可以使用*,?和[…]作为通配符,和\引用通配符或反斜杠字符。搜索其文件名和GLOB通配符相匹配的文件的内容来查找匹配使用方法:grep -H --exclude=c* “old” ./* c是通配文件名的通配符./ 指定需要先通配文件名的文件的范围,必须要给*,不然就匹配不出内容,(如果不给*,带上-r选项也可以匹配)
- –exclude-from = FILE:在文件中编写通配方案,grep将不会到匹配方案中文件名的文件去查找匹配内容
- –exclude-dir = DIR:匹配一个目录下的很多内容同时还要让一些子目录不接受匹配,就使用此选项
- –include = GLOB:仅搜索其基本名称与GLOB匹配的文件(使用–exclude下所述的通配符匹配)
- -R ,-r :以递归方式读取每个目录下的所有文件; 这相当于-d recurse选项
- 其他选项
- –line-buffered: 在输出上使用行缓冲。这可能会导致性能损失
- –mmap:启用mmap系统调用代替read系统调用
- -U:将文件视为二进制
- -z:将输入视为一组行,每一行由一个零字节(ASCII NUL字符)而不是a终止新队。与-Z或–null选项一样,此选项可以与排序-z等命令一起使用来处理任意文件名
grep的正则表达式
- \:反义字符:如"""“表示匹配”"
- [ - ]:匹配一个范围,[0-9a-zA-Z]匹配所有数字和字母
-
- :所有字符,长度可为0
- +:前面的字符出现了一次或者多次
- ^:匹配行的开始 如:’^grep’匹配所有以grep开头的行
- $:匹配行的结束 如:'grep$'匹配所有以grep结尾的行
- . :匹配一个非换行符的字符 如:'gr.p’匹配gr后接一个任意字符,然后是p
-
- :匹配零个或多个先前字符 如:’*grep’匹配所有一个或多个空格后紧跟grep的行
- .* :一起用代表任意字符
- [] :匹配一个指定范围内的字符,如’[Gg]rep’匹配Grep和grep
- [^] :匹配一个不在指定范围内的字符,如:’[^A-FH-Z]rep’匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行
- (…) :标记匹配字符,如’(love)’,love被标记为1
- <:到匹配正则表达式的行开始,如:’<grep’匹配包含以grep开头的单词的行
- >:到匹配正则表达式的行结束,如’grep>'匹配包含以grep结尾的单词的行
- x\{m\}:重复字符x,m次,如:'0{5}'匹配包含5个o的行
- x\{m,\}:重复字符x,至少m次,如:'o{5,}'匹配至少有5个o的行
- x\{m,n\}:重复字符x,至少m次,不多于n次,如:'o{5,10}'匹配5–10个o的行
- \w:匹配文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p’匹配以G后跟零个或多个文字或数字字符,然后是p
- \W:\w的反置形式,匹配一个或多个非单词字符,如点号句号等
- \b:单词锁定符,如: '\bgrep\b’只匹配grep
- [:digit:]:匹配数字
- [:lower:]:匹配小写字母
- [:upper:]:匹配大写字母
- [:alpha:]:匹配字母
- [:alnum:]:匹配字母和数字
- [:punct:]:匹配任何标点符号
- [:space:]:匹配空白字符
grep使用案例
- 统计文件中的空行数:grep -c ‘^$’ file
- 匹配时忽略字符大小写:grep -i RoOT /etc/passwd
- 显示匹配到的行,及其行后多行:grep -A 2 root /etc/passwd
- 匹配前面的字符任意次:grep “x*y” b.txt
- 匹配文本时默认处于贪婪模式,即近可能在符合条件的情况下匹配最多的字符串:grep --color “m.*e” grep_big.txt #grep按照最大长度进行匹配
- 匹配前面的字符至少m次,至多n次:grep --color “[[:alpha:]]{1,3}t” /etc/passwd
sed
sed并不改变初始化文件,改变是文件的一个拷贝,如果所有的改动没有重定向到一个文件,将输出到屏幕。
sed使用详解
sed使用方法
- sed的调用方式
- sed命令行:sed [option] COMMAND file
- sed脚本文件:sed [option] scrpts.sed file
- 第一行有sed命令解析器的sed脚本文件:script.sed [option] file
- sed选项
- -n 不打印,sed不打印编辑行到标准输出,缺省为打印所有行(编辑和未编辑)
- -p 打印编辑行
- -c 下一命令是编辑命令,使用多项编辑时加入此选项,如果只用一条sed命令,此选项无用
- -f 如果调用sed脚本文件,使用此选项
sed命令
- sed在文件查询文本的方式
- 使用行号,定位文本
- 使用正则表达式定位文本
描述 | |
---|---|
x | x为行号 |
x,y | 表示行号范围从x到y |
/pattern/ | 查询包含模式的行,如/disk/或者/[a-z]/ |
/pattern/pattern/ | 查询包含两个模式的行,如/disk/disks/ |
/pattern/,x | 在给定行号上查询包含模式的行,如/ribbon/,3 |
x,/pattern/ | 通过行号和模式查询匹配行,如3,/vdu/ |
x,y! | 查询不包含指定行号x和y的行,如1,2! |
- 基本sed编辑命令
描述 | |
---|---|
p | 打印匹配行 |
= | 显示文件行号 |
a\ | 在定位行号后附加新文本信息 |
i\ | 在定位行号后插入新文本信息 |
d | 删除定位行 |
c\ | 用新文本替换定位文本 |
s | 使用替换模式替换相应模式 |
r | 从另一个文件中读文本 |
w | 写文本到一个文件 |
q | 第一个模式匹配完成后退出或立即退出 |
l | 显示与八进制ASCII代码等价的控制字符 |
{} | 在定位行执行的命令组 |
n | 从另一个文件中读文本下一行,并附加在下一行 |
g | 将模式粘贴到/pattern n/ |
y | 字符转换,格式:[address]y/abc/xyz/ |
n | 延续到下一输入行,允许跨行的模式匹配语句 |
sed和正则表达式
sed识别任何基本正则表达式和模式及其匹配规则,如果要匹配特殊字符,必须使用(\)屏蔽特殊含义
基本sed编程举例
使用p(rint)显示行
print命令格式为[address[,address]p,显示文本行必须提供sed命令行号
- 打印指定行:sed -n ‘2p’ file
- 打印指定行的范围:sed -n ‘1,3p’ file
- 打印匹配模式的行:sed -n '/Neave/'p file
- 使用模式和行号进行查询:sed -n '4,/The/'p file
- 匹配元字符:sed -n '/\$/'p file
- 显示整个文件($意为最后一行):sed -n ‘1,$p’ file
- 匹配任意字符,后跟任意字母的0次或多次重复:sed -n '/.*ing/'p file
- 打印首行:sed -n ‘1p’ file
- 打印最后一行:sed -n ‘$p’ file
- 打印模式匹配的行号,使用格式/pattern/=:sed -e ‘/music/=’ file 或 sed -n ‘/music/=’ file
- 如果只打印行号及匹配行,必须使用两个sed命令,并使用e选项:sed -n -e ‘/music/p’ -e ‘/music/=’ file
附加、插入、修改、删除操作
- 附加文本,使用符号a\,将指定文本一行或多行附加到指定行,如果不指定文本放置位置,sed缺省放在每一行后面。附加文本不能指定范围,只允许一个地址模式。文本附加操作时,结果输出在标准输出上,不能被编辑。
#附加操作格式:
[address]a\
text\
text\
...
text
#地址指定一个模式或行号,定位新文本附加的位置
#a\通知sed对a\后的文本进行实际附加操作
#注意每一行后面的斜划线,表示换行,sed执行到这里,将创建一新行,然后插入下一文本行
#最后一行不加斜划线,sed假设附加命令结尾
- 创建sed脚本文件,输入下列命令
$pg script.sed
#!/bin/sed -f #sed命令解释行
/company/ a\ #附加操作起始位置,a\通知sed这是一个附加操作,首先插入新行
Then suddenly it hanppend #附加操作要加入到拷贝的实际文本
...
#增加执行权限
$chmod u+x script.sed
#运行
$script.sed file
- 插入文本,类似附加命令,只是在指定行前面插入,也只接受一个地址
#插入命令的格式,地址是匹配模式或行号
[address]i\
text\
text\
...
text
- 修改文本,将在匹配模式空间的指定行用新文本加以替代
#格式
[address[,address]c\
text\
text\
...
text
- 对同一文件混合修改、附加、插入操作的sed脚本
$pg mix.sed
#!/bin/sed -f
#在第一行修改
1 c\
The Dibble band were grooving.
#插入一行
/evening/ i\
They played some great tunes
#改变最后一行
$ c\
Nurse Neave was too tipsy to help?
#粘贴新行到最后一行
3 a\
where was the nurse to help?
- 删除文本
#格式
[address[,address]]d
#删除第一行
sed '1d' file
#删除第一到第三行
sed '1,3d' file
#删除最后一行
sed '$d' file
#使用正则表达式删除指定行
sed '/Neave/d' file
替换文本操作
替换命令用替换模式替换指定模式,格式为:
[address[,address]] s/ pattern-to-find /replacement-pattern/[g p w n]
- s选项是替换操作,查询pattern-to-find,成功后用replacement-pattern替换
- 如果模式包含斜杠,那么可以选择另一个字符来分隔,例如感叹号:是s!/usr/mail!/usr2/mail!
- 替换选项如下:
- g 缺省情况下只替换第一次出现,使用g选项替换全局出现的模式
- p 缺省sed将所有被替换行写入标准输出,p选项将试-n选项无效
- w 文件名,使用次选项将输出定向到一个文件
- n 1到512之间的一个数字,表示对文本模式中指定模式第n次出现的情况进行替换
- replacement-pattern是一个字符串,用来替换与正则表达式匹配的内容,在replacement-pattern部分,下列字符有特殊含义
- &:用正则表达式匹配的内容进行替换
- \n:匹配第n个字符,这个字符串在replacement-pattern中用“\(”和“\)”指定
- \:当在替换部分包含“与”符号(&),反斜杠(\)和替换命令的定界符部分包含时可用\转义它们,另外还可以用于转义换行符并创建多行replacement-pattern字符串
- 替换例子
#替换night为NIGHT
sed 's/night/NIGHT/' file
#删除$符号
sed 's/\\$//' file
#进行全局替换
sed 's/The/Wow!/g' file
#将替换结果写入一个文件
sed 's/splendid/SPLENDID/w sed.out' file
使用替换修改字符串
如果要附加或修改一个字符串,可以使用(&)命令,保存发现模式以便重新调用,然后放在替换字符串里面。
#附加一个字符串,原句:The local nurse Miss P.Neave was in attendance
$sed -n 's/nurse/"Hello" &/p' file
The local "Hello" nurse Miss P.Neave was in attendance
将sed结果写入文件命令
在sed命令中可以将结果输入文件
#格式
[address[,address]]w filename
从文件中读文本
处理文件时,sed可以从另一个文件中读文本,并将其文本附加在当前文本,此命令放在模式匹配行后
#格式
address r filename
#r通知sed将从另一个文件源读取文本,filename是其文件名
#将sedex.txt内容附加到文件quote.txt的拷贝,在模式匹配行/company/后放置附加文本
sed '/company./r sedex.txt' quote.txt
匹配后退出
有时需要模式匹配首次出现后退出sed,以便执行其他处理脚本
#格式
address q
#需要将q放在sed语句末尾
sed '/.a.*/q' filename
显示文件中的控制字符
当从其他系统复制/下载文件时,使用cat -v filename时,屏幕显示乱码,此时可以使用sed确认是否为控制字符
#格式
[address[,address]]l
#l表示为列表
awk
- 如果设置了- F选项,则a w k每次读一条记录或一行,并使用指定的分隔符分隔指定域,但如果未设置- F选项,a w k假定空格为域分隔符,并保持这个设置直到发现一新行。当新行出现时,a w k命令获悉已读完整条记录,然后在下一个记录启动读命令,这个读进程将持续到文件尾或文件不再存在
- 整个awk命令用单引号括起来
- 用花括号括起动作语句,用圆括号括起条件语句
- 用花括号括起的语句,是处理每一行时都是要执行的语句
开始块
开始块的语法格式如下:
BEGIN {awk-commands}
- 开始块就是在程序启动的时候执行的代码部分,并且它在整个过程中只执行一次。
- 一般情况下,我们可以在开始块中初始化一些变量。
- BEGIN 是 AWK 的关键字,因此它必须是大写的。
注意:开始块部分是可选的,你的程序可以没有开始块部分。
主体块
主体部分的语法格式如下:
/pattern/ {awk-commands}
- 对于每一个输入的行都会执行一次主体部分的命令。
- 默认情况下,对于输入的每一行,AWK 都会执行命令。但是,我们可以将其限定在指定的模式中。
注意:在主体块部分没有关键字存在。
结束块
结束块的语法格式如下:
END {awk-commands}
- 结束块是在程序结束时执行的代码。
- END 也是 AWK 的关键字,它也必须大写。
- 与开始块相似,结束块也是可选的
awk调用以及详解
- 有三种方式调用awk:
- awk [-F field-separator] ‘commands’ filename
- awk -F: ‘commands’ filename
- awk -f script.awk filename
- 模式和动作:任何awk语句都由模式和动作组成,在一个awk脚本中可能有许多语句,模式部分决定动作语句何时触发及触发事件,如果省略模式部分,动作时刻保持执行状态。模式可以是任何条件语句、复合语句、正则表达式,BEGIN和END是特殊的模式。BUGIN语句使用在任何文本浏览动作之前,END语句用来在awk完成文本浏览动作之后,实际动作在大括号内。
- 域和记录:awk执行时,其浏览域标志为$1,$2…$n,每一行表示一个记录
- 使用范例
- 保存awk输出
awk '{print $0}' filename > otherfile
- 打印所有记录
awk '{print $0}' filename
- 打印报告头
awk 'BEGIN {print "Name Belt\n---------------"} {print $1"\t"$4}' filename
- 打印信息尾
awk 'BEGIN {print "Name Belt\n---------------"} {print $1} END{"end-of-report"}' filename
- awk键盘输入,在命令行不输入文件
awk 'BEGIN {print "Name Belt\n---------------"} {print $1"\t"$4}'
Name Belt
---------------
>
awk正则表达式及其操作
这里正则表达式用斜线括起来,如/Green/
元字符
正则表达式常用元字符:\ ^ $ . [] | () * + ?
条件操作符
操作符 | 描述 |
---|---|
< | 小于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
>= | 大于等于 |
~ | 匹配正则表达式 |
!~ | 不匹配正则表达式 |
- 匹配
- 为使某域匹配正则表达式,须使用符合“~”后跟正则表达式,也可以用if语句,awk中if后面的条件用()括起来
- 表达式{if($4~/brown//) print},如果所在域$4包含brown,就打印
- 精确匹配
awk '$3=="48" {print $0}' filename
- 不匹配
awk '{if($4 !~ /brown/) print $0}' filename
- 小于
awk '{if($6 < $7) print $0}' filename
- 小于等于
awk '{if($4 <= $7) print $0}' filename
- 大于
awk '{if($4 > $7) print $0}' filename
- 设置大小写
为查询大小写信息,可使用[]符合
awk '/[Gg]reen' filename
复合操作符
操作符 | 描述 |
---|---|
&& AND | 与,两边必须同时满足要求 |
|| OR | 或,两边同时或一边满足要求 |
! | 非,求逆 |
awk '{if($1=="Bunny" && $4=="Yellow") print $0}' filename
awk '{if($1=="Bunny" || $4=="Yellow") print $0}' filename
awk内置变量
awk有许多内置变量设置环境信息,这些变量可以被改变
内置变量 | 描述 |
---|---|
ARGC | 命令行参数个数 |
ARGV | 命令行参数排列 |
ENVIRON | 支持队列中系统环境变量的使用 |
FILENAME | awk浏览的文件名 |
FNR | 浏览文件的记录数 |
FS | 设置输入域分隔符,等价于命令行-F选项 |
NF | 浏览记录的域个数 |
NR | 已读的记录数 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 |
RS | 控制记录分隔符 |
- ARGC支持命令行传入awk脚本的参数个数
- ARGV是ARGC的参数排列数组,其中每一元素表示为ARGV[n],n为期望访问的命令行参数
- ENVIRON支持系统设置的环境变量,要访问单独变量,使用实际变量名,如:ENVIRON[“EDITOR”]=“Vi”
- FILENAME支持awk脚本实际操作的输入文件,如果访问该变量,将告知系统目前正在浏览的实际文件
- FNR支持awk目前操作的记录数,其变量小于等于NR,如果脚本正在访问多个文件,每一个新输入文件都将重新设置此变量
- FS用来在awk中设置域分隔符,与命令行中-F选项功能相同,缺省情况下为空格,如:FS=",",设置FS变量在BEGIN部分
- NF支持记录域个数,在记录被读之后重新设置
- OFS允许指定输出域分隔符,缺省为空格,如:OFS="#"
- ORS为输出记录分隔符,缺省为新行(\n)
- RS是记录分隔符,缺省为新行(\n)
#快速查看记录个数
awk '{print NF,NR,$0} END{print FILENAME}' filename
#从文件抽取信息,首先检查文件是否有记录
awk '{if(NR>0 && $4~/Brown/) print $0}' filename
awk操作符
操作符类型 | 操作符 |
---|---|
赋值操作符 | =、+=、*=、/=、%=、^= |
条件表达式操作符 | ? |
并与非操作符 | ||、&&、! |
匹配操作符,不匹配操作符 | ~、!~ |
关系操作符 | <、<=、==、!=、>、>= |
算术操作符 | +、-、*、/、%、^ |
前缀和后缀操作符 | ++ 、– |
- 设置输入域到域变量名
一般变量名设置方式为name=$n,name为调用的域变量名,n为实际域号
awk '{name=$1;belts=$4;if(belts ~/Yellow/) print name" is belt"belts}' filename
awk 'BEGIN{BASELINE="27"} {if($6 < BASELINE) print &0}' filename
- 修改数值域取值
当在awk修改任何域时,在实际输入文件时不可修改的,修改的是保存在缓存的awk副本
awk '{if($1 == "Tansley") $6 = $6-1;print $1,$6,$7}' filename
- 修改文本域
awk '{if($1 == "Tansley") $1 = “Troll”;print $1}' filename
- 只显示修改记录
awk '{if($1 == "Tansley") {$1 = “Troll”;print $1}}' filename
- 创建新的输出域
假设创建一个基于其他域的加法新域{$4=$2+$3},这里假定记录包含3个域,则域4为新建域,保存域2和域3相加结果
awk '{$4=$2+$3;print $4}' filename
- 增加列值
tot+=$6,tot即为awk浏览整个文件的域6结果总和
awk '(tot+=$6);END{print "Club student total points:"tot}'
#如果文件很大,只想打印结果部分而不是所有记录,在语句外面加上圆括号
awk ‘{(tot+=$6)};END{print "Club student total points:"tot}'
内置字符串函数
函数 | 描述 |
---|---|
gsub(r,s) | 在整个$0中用s替代r |
gsub(r,s,t) | 在整个t中用s替代r |
index(s,t) | 返回s中字符串t的第一个位置 |
length(s) | 返回s长度 |
match(s,r) | 测试s是否包含匹配r的字符串 |
split(s,a,fs) | 使用域分隔符fs将s分成序列a |
sprint(fmt,exp) | 返回fmt格式化后的exp |
sub(r,s) | 将用s替代$0中最左边最长的字串,该字串被r匹配 |
substr(s,p) | 提取子字符串,从指定s中指定的位置p开始提取 |
substr(s,p,n) | 提取子字符串,从指定s中指定的位置p开始提取n个字符 |
- gsub
在整个记录中替换一个字符串,使用正则表达式
awk 'gsub(/4842/,4899) {print $0}' filename
- index
查询字符串s中t出现的第一位置,必须用双引号将字符串括起来
awk 'BEGIN{print index("Bunny","ny")}' filename
- length
返回字符串长度
awk '$1=="Troll" {print length($1) " " $1' filename
- match
测试目标字符串是否包含查找字符串的一部分,可以对查找部分使用正则表达式,返回值为成功出现的字符排列域,如果未找到,返回0
awk 'BEGIN{print match("ANCD",/d/)' filename
- spilt
使用split返回字符数组个数。假如有一字符串,包含指定分隔符-,如AD2-KP9-JU2-LP-1,将其划分成一个数组,使用split,指定分隔符及数组名,如split(“AD2-KP9-JU2-LP-1”,parts_array,"-"),split返回数组下标数,这里结果为4
awk 'BEGIN{print split("AD2-KP9-JU2-LP-1",parts_array,"-")'
#数组parts_array取值如下:
#parts_array[0]="AD2"
#parts_array[1]="KP9"
#parts_array[4]="1"
- sub
使用sub发现并替换模式的第一次出现位置。字符串STR包含"poped popo pill",执行sub(/op/,“OP”,STR),模式op第一次出现时,进行替换,返回结果为:“pOPed popo pill”
awk '$1=="Troll" sub(/26/,"29",$0)' filename
- substr
按照起始位置及长度返回字符串的一部分
#指定在域1第一个字符开始,返回其前面5字符
awk '$1=="Troll" {print substr($1,1,5)}' filename
字符转义
使用\转义特殊字符,如{
字符转义 | 描述 |
---|---|
\b | 退格键 |
\f | 换页 |
\n | 新行 |
\r | 回车键 |
\t | tab键 |
\ddd | 八进制值 |
\c | 任意其他特殊字符,如\\、\{等 |
#\104为D的八进制ASCII码,\141为a的八进制ASCII码
awk 'BEGIN {print "\n\May\tDay\n\nMay \104\141\171"}'
awk输出函数printf
awk printf修饰符
- | 左对齐 |
width | 步长,用0表示0步长 |
.prec | 最大字符串长度,或小数点右边的位数 |
awk printf格式
%c | ASCII字符 |
%d | 整数 |
%e | 浮点数,科学计数法 |
%f | 浮点数 |
%g | awk决定使用哪种浮点数转换e或f |
%o | 八进制数 |
%s | 字符串 |
%x | 十六进制数 |
#字符转换
echo "65" | awk '{printf "%c\n",$0}'
awk 'BEGIN{printf"%c\n",65}'
#格式化输出
awk {printf "%-15s %s\n",$1,$3}' filename
向一行awk命令传递值,或awk脚本传值
在awk执行前将值传入awk变量,需要将变量放在命令行中,格式为:
awk 命令变量=输入值
awk '{if($5 < AGE) print $0}' AGE=10 filename
awk script.awk var=value filename
awk脚本文件
#!/bin/awk -f
#print a header first
BEGIN{
print "Student Date Member No. Grade Age Points Max"
Print "Name Joined Gained Point Available"
print "=============================================="
}
#let's add the scores of points gained
(tot+=$6)
#finished processing now let's print the total and average point
END{
print "Club student total points:"tot
print "Average Club Student points:"tot/NR
}
awk数组
示例脚本
#!/bin/awk -f
BEGIN{
record="123#456#789";spilt(record,myarray,"#")
}
END{
for(i in myarray){print myarray[i]}
}
预先定义数组,并使用它与域进行比较测试
原始数据,分隔符为#:
Yellow#Junior
Orange#Senior
Yellow#Junior
Purple#Junior
Brown#Junior
White#Senior
Red#Junior
脚本功能:Yellow、Orange和Red的数量;Junior和Senior数量
#!/bin/awk -f
BEGIN{
FS="#"
#load the colours we are interested in only
belt["Yellow"]
belt["Orange"]
belt["Red"]
#load the type
student["Junior"]
student["Senior"]
}
#loop hte array that holds the belt against field-1
#if match,keep a running tatal
{
for(colour in belt){if($1==colour) belt[colour]++}
}
#loop[ the array that holds the student type against field-2
#if match ,keep a running t0tal
{
for(type in student){if($2==type ) student[type ]++}
}
#finish processing so print out the matches for each array
END{
for(colour in belt) print "The club has",belt[colour],colour,"Belts"
for(type in student) print "The type has",student[type],type,"Student"
}
测试数组中的成员资格
#如果存在则返回1,否则返回0
if("BASIC" in array)
print "FIND"
删除数组元素
#从数组中删除一个元素
delete array[sub]
条件、循环和数组
条件语句
格式:
if(expression)
action1
[else
action2]
awk 'if($1>=65){grade="Pass"};else {grade="Fail"};print $0' filename
#!/bin/awk -f
if(agv>=90)
grade="A"
else if(avg>=80)
grade="B"
else
grade="F"
条件操作符
格式:
expr ? action1 : action2
#!/bin/awk -f
grade = (avg >= 65) ? "Pass" : "Fail"
while循环
格式:
while(condition)
action
#!/bin/awk -f
i = 1
while(i<=4){
print $i
++i
}
do循环
格式:
do
action
while(condition)
#!/bin/awk -f
BEGIN{
i=1
do{
print $i
++i
}while(x<=4)
}
for循环
格式:
for(set_counter; test_counter; increment_counter)
action
#!/bin/awk -f
for(i=1; i<=NF; i++)
print $i
影响流控制的语句
- break语句退出循环
- continue语句在到达循环底部之前终止当前的循环,并从循环的顶部开始一个新的循环
- next语句能够导致读入下一个输入行,并返回到脚本底部,可以避免对当前输入行执行其他的操作过程
- exit语句使主输入循环退出并将控制转移到END规则,exit语句可以使用一个表达式作为参数,表示awk的退出状态
自定义函数
格式:
function name(parameter-list){
statements
}
function insert(STRING, POS, INS){
before_tmp=substr(STRING, 1, POS)
after_tmp=substr(STRING, POS + 1)
return before_tmp INS after_tmp
}
{
print "Function returns",insert($1, 4, "XX")
}