Linux 三剑客

简介

 Linux 三剑客具体指什么?

第一个工具是 grep,grep 会根据正则表达式查找相关内容并打印对应的数据。

第二个工具是 awk,awk 的名字来源于三个作者的名字简称,它可以根据定位到的数据行处理其中的分段。

第三个工具是 sed,它是 stream editor 流式编辑器的简称,可以定位到数据行并对数据进行增删改查操作。

因为它们三个组合使用的功能非常的强大,几乎完美的应对了 Shell 中的数据分析场景,于是人们把这三个工具统称为 Linux 三剑客。

价值

grep 相当于 SQL 的 select *from table,它可以进行数据的查找与定位。

awk 相当于 SQL 的 select field from table,它可以进行数据切片。

sed 相当于 SQL 的 update table set field=new where field=old,它可以对数据进行修改。

 

你可以发现,grep 和 awk 可以进行组合使用,来达到查找数据并对数据进行分割的目的,grep 也可以与 sed 组合使用,达到查找数据并修改的目的,它们三个还可以组合在一起使用来完成一系列的操作,就相当于大数据处理中的 Map-Reduce,我们接下来看如何具体的使用它们。

grep      

首先,我们来看下如何使用 grep,grep 用于根据正则表达式查找相关内容并打印对应的数据,我们打开 Shell 环境,通过 vim/tmp/hello.txt 命令创建一个文件,并在文件内输入三条数据:

    hello from hogwarts

    hello from sevenriby

    hello from testerhome

然后通过 grep hogwarts /tmp/hello.txt 指令查找数据,指令中间的参数是正则表达式,指令后面的参数是文件名。

你可以看到 grep 把 hello from hogwarts 从文件中提取出来。    

你还可以通过 grep 把 testerhome 提取出来,通过 cat 指令可以看到在 hello.txt 中有三行数据。

如果我们输入 grep hello 指令,它会把三条数据都提取出来。这就是 grep 的第一个作用,根据指定的正则表达式查取对应的数据,我们上面的演示用的是简单的字符串。

接下来,我们学习如何使用正则表达式获取以字母 s 或 t 开头的后面跟任意两个字符的数据,输入 grep "[st].." /tmp/hello.tex 指令,其中 [] 表示正则表达式,..表示后面跟任意的两个字符,你可以看到输出了两条数据。

我们还可以通过 -o 指令只打印匹配的内容,输入 grep -o "[st].." /tmp/hello.tex 指令,你可以看到只打印了匹配到的内容,而不是整条数据。
grep 还有一些其他的指令,比如 -i 可以忽略字符大小写。

-v 表示将匹配到的内容过滤掉,比如我们输入 grep -v "[st].." /tmp/hello.tex 指令,只显示了一条数据,过滤掉了匹配正则条件的内容。
-o 表示只打印匹配的数据,-E 表示支持使用扩展正则表达式,我们接下来详细了解下 pattern 正则表达式。

我把正则表达式分为两类,第一类称为基本表达式,基本表达式包括了典型的正则标识符。

    ^表示开头;

    $表示结尾;

    []表示任意匹配项;

    *表示0个或多个;

    .表示任意字符。

第二类是扩展表达式,它在基础表达式的基础上做了一些扩展,支持了更高级的语法和更复杂的条件。

    ?表示非贪婪匹配;

    + 表示一个或多个;

    () 表示分组;

    {} 表示一个范围的约束;

    | 表示匹配多个表达式中的任何一个。  

但如果你的指令中不含 -E,则指令不支持扩展正则,这个时候你会发现它什么都匹配不到。

如果不使用 -E,我们可以使用 \ 转义符对匹配条件进行转义,也可以达到同样的效果

awk

awk 是 Linux 下的一个命令,同时也是一种语言解析引擎,它的功能非常强大,具备完整的编程特性,可以执行命令、进行网络请求等操作。所以精通 awk 是一个 Linux 工作者必备的技能。我们接下来看下 awk 的语法 awk 'pattern{action}' 的相关知识,pattern 是匹配条件,action 表示具体需要做的处理。


pettern 语法在一定程度上可以代替 grep。

举个例子,使用双 / 表示一个正则匹配,我们输入 awk '/[st]../' /tmp/hello.txt 指令,你可以看到和 grep 一样,轻松地打印出匹配到的内容,所以在一定程度上 awk 可以替代 grep,但它没有使用 grep 简洁。

还有表示区间选择,比如我们在 1、2、3 之间,使用 awk '$0>2' 指令打印大于 2 的数据 3。

还有一个参数叫 NR,代表记录数,比如输入 awk 'NR>1' /tmp/hello.tex 指令打印去掉第一行的数据。

     

pattern有非常丰富的语法,你可以课后自己进行练习,同时 awk 还有几个标准的内置变量。

    FS 表示字段分隔符

    OFS 表示输出数据的字段分隔符

    RS 表示记录分隔符

    ORS 表示输出字段的行分隔符

    NF 表示字段数

    NR 表示记录数            

比如,我们输入 awk '{print NR,NF}' /tmp/hello.txt 指令,输出显示 hello from hogwarts 被空格分隔成了三个字段,并且 hello.txt 文件中的三条数据字段数都是 3。 

我们输入 awk -Fo '{print NR,NF}' /tmp/hello.txt 指令,输出显示我们以 o 为分隔符,将 hello from hogwarts 分为了 4 个字段,下面两条数据以此类推。

 

sed      
然后我们再看第三个工具流式编辑器 sed。sed 的语法和 awk 有点类似,只不过具体的用法不太一样。

    sed[addr]X[opptions],其中 [] 定义了一个范围,x位是具体操作,options表示进行数据修改的选项。

    -e 表示可以指定表达式。

    sed -n '2p' 2 表示打印第二行的数据。

    s 表示查找并替换。

    -i 表示直接修改源文件

    -E 支持扩展表达式。

比如我们输入 sed 's#testerhome#world#' /tmp/hello.txt 指令,其中 s 后面可以跟任意符号,比如 / 或 # 都可以表示分隔符,它会用后面的内容替换前面的内容。

/g 表示除了替换第一个匹配的字符以外还会把第二个也替换掉,这就是 sed 的用法,你看到 sed 主要帮助我们编辑文件。

     

那么关于它的匹配符 pattern,你可以给定具体的行数也可以通过正则匹配一个范围,在某个范围内做一个修改;区间范围也是一个类似的用法,你会发现它和 awk 语法很像。

 

 



     

action 与 awk 的不同点在于 awk 专注于数据的提取,而 sed 更专注于数据的修改,sed 的重要作用是完成对数据的增删改查工作,比如:

    d 是删除

    p 是打印

    s 是查找并进行替换

    \1 \2 可以根据匹配的数据进行分组处理

所以 sed 也是一个灵活强大的工具,一旦你掌握了上面的全部内容,那么说明你对三剑客已经入门了。

高阶:

Shell 输入输出 

首先需要了解 Shell 的输入输出,在 Shell 里,每个指令其实都是一个进程,和我们的被测程序一样,这个进程也有输入和输出。 比如,你可以使用 read 读取输入,并赋值给变量,也可以使用 echo、print 输出变量。而在 Shell 输入输出指令里面有一个特别需要我们注意的功能叫作管道,用 | 表示,它可以将上一个指令的输出自动变成下一个指令的输入。

文件描述符

接下来,我们来看一下管道的具体用法。如图所示,Shell 下任何程序都有输入和输出,这里需要额外注意的是错误输出,比如我们输入 ls dddd 指令。

因为 dddd 文件是不存在的,所以会打印了一个独立显示的报错信息,我们就称之为错误输出。

输入 ls -l /tmp appium.log 指令,可以打印一个正确的输出。

输入是一个读取文件的过程,比如我们输入 grep "hogwarts" /tmp/hello.txt 指令便是从 hello.txt 文件中读取 hogwarts。

但如果我们不传递给指令一个文件,会发生什么样的效果?比如输入 grep "hogwarts" 指令,你会发现什么都没有显示,继续输入 xxx、dddd 仍没有任何反应,直到输入 hogwarts 时,系统才会输出 hogwarts,我们看到如果不传递输入文件,grep 会默认从当前输入读取内容。

 

举个例子,比如我们输入 echo hello | gerp hogwarts 指令,打印一个 hello 传给 grep hogwarts,这个时候,你会发现没有任何输出,这是为什么呢?

 

我们把指令分为两部分执行,第一部分执行 echo hello,这个指令没有任何输入但是有输出

然后,将 echo hello 通过管道传递给 grep hogwarts,此时管道已经找到输入内容 echo hello,于是便不再从当前窗口读取数据,但因为读入的内容实际是没有输入的所以会得不到任何输出。

我们应该如何正确操作呢,输入 echo hello hogwarts | gerp hogwarts 指令,你会看到输出了正确的内容。因为上一个命令输入了 hello hogwarts,再经 grep 后输出。你可以看到通过管道我们可以让 Linux 三剑客的功能发挥到一个新的高度,有了管道很多的操作就变得非常简单易处理。

再举个例子,首先通过 cat /tmp/hello.txt 指令打印 hello.txt 文件。

然后通过管道打印包含 testerhome 的信息行。

如果此时我们只想得到 testerhome 这个单词怎么办呢?输入 cat /tmp/hello.txt | grep testerhome | awk '{print $3}' 指令就可以单独打印 testerhome 了,因为 hello from testerhome 是以空格隔开的,所以指令中的 $3 表示第三个元素。

我们再继续使用管道将 testerhome 中的 tester 替换成 dev,输入 cat /tmp/hello.txt | grep testerhome | awk '{print $3}' | sed 's#tester#dev#' 指令,你可以看到 testerhome 就变成了devhome 了。

 

posted @ 2020-12-14 17:51  软件测试大田  阅读(207)  评论(0编辑  收藏  举报