三剑客基础详解
[TOC]
三剑客之grep详解
通配符与正则表达式这两口子可以说贯穿三剑客始终,甚至时贯穿linux始终,这样说,我觉得并不夸张。因而在写三剑客之前,先捋一捋这些这些知识点就很有必要了。
相对而言正则用于三剑客多少量,通配符用于Linux命令行多少量。
1.通配符
| 通配符 | 形容 |
|---|---|
| * | 任意多个字符 |
| ? | 任意单个字符 |
| . | 当前目录 |
| .. | 上级目录 |
| ; | 命令分隔符 |
| ~ | 当前客户家目录 |
| $ | 引用变量 |
| ! | 逻辑运算非 |
| && | 前一个命令执行成功,则执行后面的命令 |
| || | 当前命令执行失败,则执行后面命令 |
| ‘ | 单引号,原样输出,所见即所得 |
| “ | 双引号,可以置换变量的值,不加引号相当于双引号 |
| ` | 反引号中的内容会被优先解析 |
| – | 之前所在路径 |
| {} | shell脚本命令组合;命令行中内容序列 |
| > | 重定向覆盖 |
| >> | 重定向追加 |
2.基础正则
- 锚定行首,如word表示以word开头的行
表示以word结尾的行
- ^$则表示空行
- . 任意单个字符
- *匹配其前面字符任意屡次
- .*表示匹配所有字符
- \ 转义字符,使得特殊字符失去特殊含义
- []匹配范围内的单个字符
- [^]匹配范围外的单个字符
- 指定匹配次数的范围,即分组
- \{n,m\} 匹配前面字符n到m次
- \{n,\} 匹配前面字符至少n次
- \{,m\}匹配前面字符至多m次
- \{n\} 匹配前面字符n次
在扩展正则中可以去掉转义符,即egrep 或者者 grep -E
3.grep 讲解
3.1语法格式
grep [OPTIONS] [PATTERN] [FILE..]
grep [选项] [过滤的内容] [源文件]
3.2常用参数
- -n 显示过滤内容所在行数
- -o 只显示匹配到的内容,不会按行输出
- -i 忽略大小写
- -v 反向选择,显示未匹配到的内容
- -E 支持拓展正则
- -A 匹配到的行后面几行,即After
- -B 匹配到的行前面几行,即Before
- -C 配到的行前后几行,即context上下文
#准备好试验内容randolf@localhost:~/test $ ls && cat sed2.txt inittab sed2.txt test.md5 test.txtOh/my/god,dear me!hello wordyou are so cutewhat do you think of the partyI am so glad to tell you that I am crazy about Linux!Linux is better than Windows much more.#显示以hello开头的行,并且显示其所在行数randolf@localhost:~/test $ grep -n "^hello" sed2.txt 2:hello word#显示以cute结尾的行,并且只打印匹配到的内容randolf@localhost:~/test $ grep -o "cute$" sed2.txt cute#显示不包含单词you的行randolf@localhost:~/test $ grep -v "you" sed2.txt Oh/my/god,dear me!hello wordLinux is better than Windows much more.4.拓展正则
- + 重复匹配前面字符1次及1次以上(区别于*匹配0次至屡次)
- ? 重复匹配前面字符0次或者者1次(.表示任意一个字符,不是匹配)
- | 可以同时过滤多个字符
- () 分组过滤,向后引用(也叫方向引用),将组中的内容作为一个整体来匹配,突破了只能匹配前面单个字符的限制,常常结合分组的使用
#新建测试文本testrandolf@localhost:~/test $ cat > test<<EOF> gods> gds> goods> gooods> goads> EOF#分别演示+ ? . 的用法randolf@localhost:~/test $ egrep "go?ds" test godsgdsrandolf@localhost:~/test $ egrep "go+ds" test godsgoodsgooodsrandolf@localhost:~/test $ egrep "go.ds" test goodsgoads#演示 | 的多字符过滤randolf@localhost:~/test $ egrep "gds|goods" test gdsgoods#向后引用结合分组的演示randolf@localhost:~/test $ echo "goodsgoods" >> testrandolf@localhost:~/test $ grep -E '(goods){2}' test goodsgoods5.POSIX字符类
| 括号类 | 含义 |
|---|---|
| [:alnum:] | 字母数字字符 |
| [:alpha:] | 字母字符 |
| [:digit:] | 数字字符 |
| [:graph:] | 非空白字符(非空格、控制字符等) |
| [:lower:] | 小写字母 |
| [:print:] | 与[:graph:]类似,但是包含空格字符 |
| [:punct:] | 标点字符 |
| [:upper:] | 大写字母 |
| [:xdigit:] | 允许十六进制的数字 |
| [:cntrl:] | 控制字符 |
字符类用的较少,放在这里仅作备用
三剑客之sed讲解
sed全称为Stream Editor即流编辑器,用于过滤和转换文本,常用的功能包括增删改查,过滤,取行。
1.sed的执行流程
sed作为流编辑器仅支持单行操作,每次启动sed进程时,linux会为它在内存中单独分配一个专属的空间,我们称其为模式空间。sed每次只读取文本中的一行到模式空间中,执行完指定的sed内置命令后,默认将模式空间中的文本打印到屏幕上,而后删除模式空间中的文本,再读取原文本中的第二行,重复上面的操作,直至文本的最后一行。
sed1
2.语法格式
sed [option] [AddressCommand] [input-file]
2.1option:
- -n 静默模式
- -i 编辑原文件
- -r 支持拓展正则
2.2 Address:
这里的地址我们指sed所挑选的目标行,支持模式匹配,即便用通配符等。
| 地址表示形式 | 形容 |
|---|---|
| 1 | 操作第1行 |
| 1,3 | 操作第1到3行 |
| 1,+3 | 操作第1行以及后面3行(1到4行) |
| 1,$ | 操作第1行到最后一行 |
| 1~2 | 通用(nm),从第n行开始,步进为进行m挑选,如12表示第1、3、5….行 |
以上地址表示皆支持模式匹配,如
| 地址表示形式 | 形容 |
|---|---|
| /word/ | 操作所有匹配到word这个单词所在行 |
| /word/,/Linux/ | 操作匹配到word的行一直到匹配到Linux的行,遵循懒汉模式的搜索匹配 |
| /word/,+3 | 操作匹配到word的行以及后面三行(从第一次匹配到word开始) |
| /word/,$ | 操作匹配到word的行一直到最后一行(从第一次匹配到word开始) |
懒汉模式匹配:第一次搜索到的结果(word)作为开始,并且第一次搜索到的结果作为(Linux)作为结尾
2.3 Command
此处命令指的是sed编辑器的内置命令,而不是linux的系统命令
现在创立如下文件touch /home/randolf/test/sed.txt
并且写入内容,作为试验文本:
cat >sed.txt<<EOF>0.I am the whole word>1.hello word>2.you are so cute>3.what do you think of the party>4.I am so glad to tell you that I am crazy about Linux!>5.Linux is better than Windows much more.>EOF地址表示形式与命令的搭配太多不可能逐个演示,下面选取典型场景,为大家演示
p 打印行
#打印第2到3行randolf@localhost:~/test $ sed '2,3p' sed.txt0.I am the whole word1.hello word1.hello word2.you are so cute2.you are so cute3.what do you think of the party4.I am so glad to tell you that I am crazy about Linux!5.Linux is better than Windows much more.咦?怎样打印这么多东西。我明明只选取2到3行呀。还记得上面说的嘛,“执行完指定的sed内置命令后,默认将模式空间中的文本打印到屏幕上”,没错,sed除了将我们选取的内容打印一遍,还没有不记得自己原本的职责,即打印一遍模式空间中的内容。所以就看了以上打印内容,2到3行打印了两遍。那假如不想要sed默认打印模式空间咋办?真相只有一个!选项-n,他表示静默模式,即不再默认打印模式空间中的内容,试试看喽。
randolf@localhost:~/test $ sed -n '2,3p' sed.txt1.hello word2.you are so cute#顿时清新多了,舒服#打印匹配到word的行一直到匹配到Linux的行,遵循懒汉模式的搜索匹配randolf@localhost:~/test $ sed -n '/word/,/Linux/p' sed.txt 0.I am the whole word1.hello word2.you are so cute3.what do you think of the party4.I am so glad to tell you that I am crazy about Linux!比照原来的文本中,含单词word的行有两行,同样含单词Linux的行也有两行,而作为起始行与结束行的都时匹配到的第一个结果,即遵循懒汉模式
s 替换行
#将第一行中"the whole word"替换为"a student"randolf@localhost:~/test $ sed 's/the whole word/a student/' sed.txt 0.I am a student1.hello word2.you are so cute3.what do you think of the party4.I am so glad to tell you that I am crazy about Linux!5.Linux is better than Windows much more.#这里替换的只是sed模式空间中的内容,若想要直接操作员文本,可以使用选项-irandolf@localhost:~/test $ sed -i 's/the whole word/a student/' sed.txt#当我们直接操作原文本时,同样也是不打印模式空间的randolf@localhost:~/test $ cat sed.txt 0.I am a student1.hello word2.you are so cute3.what do you think of the party4.I am so glad to tell you that I am crazy about Linux!5.Linux is better than Windows much more.sed的内置命令s中的边界符除了“/”,还可以使用“#”、”@”等特殊符号,常用于避免和原文本中的符号产生冲突,尽管也可以使用转义符避免冲突,不过转义符可能让你眼花缭乱。。
举个例子
#使用vim将刚刚的文本第一行修改为"0.Oh/my/god,dear me!",并执行复制cp sed.txt sed2.txt#目标:将Oh/my/god修改为honey#1.使用"@"作为定界符修改sed.txtrandolf@localhost:~/test $ sed 's@Oh/my/god@honey@' sed.txt |head -n 10.honey,dear me!#2.使用"/"作为定界符修改sed2.txtrandolf@localhost:~/test $ sed 's/Oh\/my\/god/honey/' sed2.txt |head -n 10.honey,dear me!#尽管都能实现操作,可这视觉效果实在不堪,让我这老花眼晕一会。。。d 删除行
#读入模式空间后直接删除读入的行,不让他打印到屏幕上来#删除1到3行randolf@localhost:~/test $ sed '1,3d' sed.txt 3.what do you think of the party4.I am so glad to tell you that I am crazy about Linux!5.Linux is better than Windows much more.#操作原文本,删除第一行#先瞄一眼,未删除之前第一二行是啥randolf@localhost:~/test $ sed -n '1p' sed.txt| head -n 20.Oh/my/god,dear me!1.hello word#执行删除命令randolf@localhost:~/test $ sed -i '1d' sed.txt randolf@localhost:~/test $ sed -n '1p' sed.txt| head -n 11.hello word#看到了吧,原文件中第1行成功删除,本来的第2行上位成第一行a 目标行后面追加一行
#最后一行后面增加一行内容,"The earth is beautiful"randolf@localhost:~/test $ sed -i '$a The earth is beautiful' sed.txt randolf@localhost:~/test $ sed -n '$p' sed.txt The earth is beautiful#成功!!!i 目标行前面追加一行
#第一行前面增加一行内容,"This is a start line added just now!"randolf@localhost:~/test $ sed -i '1i This is a start line added just now!' sed.txt randolf@localhost:~/test $ sed -n '1p' sed.txt This is a start line added just now!#So easy!!!三剑客之Awk
awk作为三剑客中最最复杂的老大哥,常常被称为awk语言,那么,详细解释是不可能的,这辈子都不可能的。。。聊点皮毛
1.awk初见面
1.1awk的简单详情
1977年由Alfred Aho 、Peter Weinberger 和 Brian Kernighan这三位同学创造,并以其名字的首字母命名该语言。
版本:awk同样分为不同的版本,如gawk、dawk、pawk,mawk等,在Linux里常使用的是gawk(红帽系列)、和mawk(乌班图系列)。我在使用的是rhel的社区版centos7,所以记录的也将是gawk的使用。
1.2 awk的工作机制
相似其余两位剑客(sed、grep),awk也是按行读取,过滤客户给定的匹配模式,并且执行特定的解决动作
组成部分(重要):pattern {action}
即匹配的模式(支持正则)和对匹配到的内容所执行的解决动作
两个特殊的模式:BEGIN END顾名思义,这两家伙分别表示在读取模式所匹配的数据之前执行,和在一律读取完数据之后执行
两个注意点:1.若未给定模式,则匹配所有 2.若没有指明解决行为,则默认执行打印动作print
毫不夸张地说,了解awk的组成,也就掌握其一半的使用能力了。
2.常用选项
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...Usage: awk [POSIX or GNU style options] [--] 'program' file ...POSIX options: GNU long options: (standard) -f progfile --file=progfile #从脚本中加载awk的命令 -F fs --field-separator=fs #指定分隔符 -v var=val --assign=var=val #解决动作执行前设置一个变量val-f加载的脚本中放置的是awk结构的命令,包括 pattern {action}
当需要指定多个分隔符时,可以以通过内置变量FS设置
多个动作解决条件以空格隔开,如{action1} {action2} {action3}…..
#案例素材randolf@zrm:~/test $ cat test centos|ubuntu|archapple,orange,banana dog cat#以|为分隔符,打印$3、$NFrandolf@zrm:~/test $ awk -F '|' '{print $NF}' testarchapple,orange,banana dog catrandolf@zrm:~/test $ awk -F '|' '{print $3}' testarchNF为内置变量,表示当前记录的个数,那么思考一下,$3的打印结果为什么第二行为空呢?我们前面提到awk是按行读取的,所以对于awk来说每一行就是一个操作范围,第一行被"|"分为三个字段,因而记录个数为3,即$NF的值是3,所以第一行的值输出相同;而第二行没有分隔符"|",所以整行只有一个字段记录,因而$NF的值为1,输出整行,而$3在第二行不存在,所以输出空白行。#重新编辑test文本内容randolf@zrm:~/test $ cat testcentos|ubuntu|archapple,orange,banana dog catnihaoa,xiongdiwoshiyizhishuaiguo#编写简单脚本供awk调用randolf@zrm:~/test $ echo "/^$/ {print \"我是一只空行\"}" > haha #双引号需要转义randolf@zrm:~/test $ cat haha /^$/ {print "我是一只空行"} #注意中间有空格randolf@zrm:~/test $ awk -f awk.sh test我是一只空行我是一只空行#BEGIN字段应用举例(2014年兄弟连 沈超李明老师经典教程)randolf@zrm:~/test $ awk '{FS=":"} {print $1}' /etc/passwd |head -4root:x:0:0:root:/root:/bin/bashbindaemonadmrandolf@zrm:~/test $ awk 'BEGIN{FS=":"} {print $1}' /etc/passwd |head -4rootbindaemonadm#内容太长仅以4行为例,看到了么,未加BEGIN时第一行没有被分隔,哈哈,是不是蒙圈了?其实很好了解,awk会事前读取一行文本的内容,而后才会去找前面的条件,此处为设定的分隔符,嗯哼?想一想前面提到过的BEGIN的定义,BEGIN做两大特殊模式之一,表示在读取模式所匹配的数据之前执行,所以呢,加上BEGIN后,awk会先读取BEGIN后的条件。^_^3.内置变量
| 变量名称 | 形容 |
|---|---|
| ARGC | 命令行参数个数 |
| FILENAME | 当前输入文档的名称 |
| FNR | 当前输入文档的记录编号,多个输入文档时有用 |
| NR | 输入流当前记录编号 |
| NF | 当前记录的字段个数 |
| FS | 字段分隔符 |
| OFS | 输出字段分隔符,默认是空格 |
| ORS | 输出记录分隔符,默认换行符 \n |
| RS | 输入记录分隔符,默认换行符 |
4.表达式与操作符
4.1表达式的组成部分
表达式由变量,常量,函数,正则表达式,操作符组成
awk中变量有字符变量和数字变量,假如在awk中定义变量没有初始化,则初始化值为空字符或者0。字符操作必需加引号,如 a=”hello word”
4.2 常见操作符
+ – * / (加减乘除。。)
% 取余 ^ 幂运算 ++ — += -= *+ /= ‘>’
< >= <= == 等于 != ~匹配 !~不匹配 &&与 ||或者#操作符简单举例randolf@zrm:~/test $ echo test | awk 'x=2 {print x+=1}'3randolf@zrm:~/test $ echo hello | awk 'x=1,y=3 {print x*2,y*3}'2 9#表达式与模式END结合使用randolf@zrm:~/test $ awk '/^$/ {x+=1} END {print x}' test2#打印root客户的UID,cat一下知道,/etc/passwd文件中第三个字段是客户的UIDrandolf@zrm:~/test $ awk -F: '$1~/root/ {print $3}' /etc/passwd0