Linux学习|Gentoo/Arch/FreeBSD

三剑客基础详解

2020-03-09  本文已影响0人  渊亭无迹

三剑客基础详解

[TOC]

三剑客之grep详解

通配符与正则表达式这两口子可以说贯穿三剑客始终,甚至时贯穿linux始终,这样说,我觉得并不夸张。因此在写三剑客之前,先捋一捋这些这些知识点就很有必要了。

相对而言正则用于三剑客多一些,通配符用于Linux命令行多一些。

1.通配符

通配符 描述
* 任意多个字符
任意单个字符
. 当前目录
.. 上级目录
命令分隔符
~ 当前用户家目录
$ 引用变量
! 逻辑运算非
&& 前一个命令执行成功,则执行后面的命令
|| 当前命令执行失败,则执行后面命令
' 单引号,原样输出,所见即所得
" 双引号,可以置换变量的值,不加引号相当于双引号
` 反引号中的内容会被优先解析
- 之前所在路径
{} shell脚本命令组合;命令行中内容序列
> 重定向覆盖
>> 重定向追加

2.基础正则

在扩展正则中可以去掉转义符,即egrep 或者 grep -E

3.grep 讲解

3.1语法格式

grep [OPTIONS] [PATTERN] [FILE..]

grep [选项] [过滤的内容] [源文件]

3.2常用参数

#准备好实验内容
randolf@localhost:~/test $ ls && cat sed2.txt 
inittab  sed2.txt  test.md5  test.txt
Oh/my/god,dear me!
hello word
you are so cute
what do you think of the party
I 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 word
Linux is better than Windows much more.

4.拓展正则

  1. + 重复匹配前面字符1次及1次以上(区别于*匹配0次至多次)
  2. ? 重复匹配前面字符0次或者1次(.表示任意一个字符,不是匹配)
  3. | 可以同时过滤多个字符
  4. () 分组过滤,向后引用(也叫方向引用),将组中的内容作为一个整体来匹配,突破了只能匹配前面单个字符的限制,常常结合分组的使用
#新建测试文本test
randolf@localhost:~/test $ cat > test<<EOF
> gods
> gds
> goods
> gooods
> goads
> EOF
#分别演示+ ? . 的用法
randolf@localhost:~/test $ egrep "go?ds" test 
gods
gds
randolf@localhost:~/test $ egrep "go+ds" test 
gods
goods
gooods
randolf@localhost:~/test $ egrep "go.ds" test 
goods
goads
#演示 | 的多字符过滤
randolf@localhost:~/test $ egrep "gds|goods" test 
gds
goods
#向后引用结合分组的演示
randolf@localhost:~/test $ echo "goodsgoods" >> test
randolf@localhost:~/test $ grep -E '(goods){2}' test 
goodsgoods

5.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:

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

地址表示形式与命令的搭配太多不可能一一演示,下面选取典型场景,为大家演示

#第一行前面添加一行内容,"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|arch
apple,orange,banana dog cat
#以|为分隔符,打印$3、$NF
randolf@zrm:~/test $ awk -F '|' '{print $NF}' test
arch
apple,orange,banana dog cat
randolf@zrm:~/test $ awk -F '|' '{print $3}' test
arch

NF为内置变量,表示当前记录的个数,那么思考一下,$3的打印结果为什么第二行为空呢?
我们前面提到awk是按行读取的,所以对于awk来说每一行就是一个操作范围,第一行被"|"分为三个字段,因此记录个数为3,即$NF的值是3,所以第一行的值输出相同;而第二行没有分隔符"|",所以整行只有一个字段记录,因此$NF的值为1,输出整行,而$3在第二行不存在,所以输出空白行。
#重新编辑test文本内容
randolf@zrm:~/test $ cat test
centos|ubuntu|arch
apple,orange,banana dog cat

nihaoa,xiongdi

woshiyizhishuaiguo
#编写简单脚本供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 -4
root:x:0:0:root:/root:/bin/bash
bin
daemon
adm
randolf@zrm:~/test $ awk  'BEGIN{FS=":"} {print $1}' /etc/passwd |head -4
root
bin
daemon
adm
#内容太长仅以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}'
3
randolf@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}' test
2
#打印root用户的UID,cat一下知道,/etc/passwd文件中第三个字段是用户的UID
randolf@zrm:~/test $ awk -F: '$1~/root/ {print $3}' /etc/passwd
0


上一篇 下一篇

猜你喜欢

热点阅读