Linux系统开发: 学习linux三剑客(awk、sed、grep)(上)

简介: Linux系统开发: 学习linux三剑客(awk、sed、grep)(上)

一、前言

Linux中的三个命令awk、sed、grep在业界被称为“三剑客”,grep擅长查找,sed擅长取行和替换,awk擅长运算。


我们知道Linux下一切皆文件,对Linux的操作就是对文件的处理,那么怎么能更好的处理文件呢?这就要用到三剑客命令。


三剑客与正则表达式息息相关,正则表达式是为了处理大量的文本|字符串而定义的一套规则和模版,这个模版是由一些普通字符和一些元字符组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义。正则表达式详情可参看资料《linux正则表达式》。


三剑客与正则表达式是什么关系呢?

三剑客就是普通的命令,有的把他们叫做工具。而正则表达式就好比一个模版,而linux下一般只有三剑客能读懂这个模版。

image.png

二、grep命令

2.1 grep命令功能

grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。


Unix的grep家族包括grep、egrep和fgrep。egrep和fgrep的命令只跟grep有很小不同。egrep是grep的扩展,支持更多的re元字符, fgrep就是fixed grep或fast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示回其自身的字面意义,不再特殊。linux使用GNU版本的grep。它功能更强,可以通过-G、-E、-F命令行选项来使用egrep和fgrep的功能。


查找内容可以用双引号括起来,也可以不用,建议使用双引号,双引号中一些特殊符号要注意使用转义字符。


格式:grep  [OPTIONS]  PATTERN  [FILE...]


grep默认不支持扩展正则,因此扩展正则表达式的符号对于grep来说就等同于普通字符含义,因此,想让grep直接处理正则符号必须通过转义字符\{\}来处理。


grep -E 强制让grep直接认识正则符号,不需要再进行转义,egrep 等效grep -E 天生就能认识正则符号;我们平时备份可以通过cp 文件名{,.bak}的形式进行,避免再打一次文件名


2.2 支持的选项参数

-a 不要忽略二进制数据。


-A <显示行数> 除了显示符合范本样式的行之外,并显示该行之后的指定几行内容。


-B<显示行数> 除了显示符合范本样式的行之外,并显示该行之前的指定几行内容。


-C<显示行数>  除了显示符合范本样式的那一行之外,并显示该行前后指定几行的内容。


-b 在显示符合范本样式的那一行之外,并显示字节偏移量。-c 只计算显示符合范本样式的行数,不显示详细内容


-d<进行动作> 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep命令将回报信息并停止动作。


-e<范本样式> 指定字符串作为查找文件内容的范本样式。


-E 将范本样式为延伸的普通表示法来使用,意味着能使用扩展正则表达式。


-f <范本文件> 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一列的范本样式。


-F 将范本样式视为固定字符串的列表。


-G 将范本样式视为普通的表示法来使用。


-h 在显示符合范本样式的那一列之前,不标示该列所属的文件名称。


-H 在显示符合范本样式的那一列之前,标示该列的文件名称。


-i 忽略字符大小写的差别。


-l 列出文件内容符合指定的范本样式的文件名称。


-L 列出文件内容不符合指定的范本样式的文件名称。


-n 在显示符合范本样式的那一列,标示出该列的编号。


-q 不显示任何信息。


-R/-r 此参数的效果和指定“-d recurse”参数相同,表明查找路径为目录


-s 不显示错误信息。


-v 反转查找,显示不符合模式的所有信息


-w 只显示全字符合的列。


-x 只显示全列符合的列。


-y 此参数效果跟“-i”相同。


-o 只输出文件中匹配到的部分。


--color=auto 把匹配部分标记出来,要想当前终端后续使用都要标记匹配部分,可用alias命令重新封装grep。


#alias grep=’grep --color=auto’


2.3 常用示例

在文件中查找内容


成功会输出所有包含查找内容的行,否则输出为空。

$  grep  bash   file_read.sh   #在file_read.sh内查找bash  
$  grep  "bash"   file_read.sh  --color=auto  #两者效果相同,并且标记颜色
$ grep  "bash"   file_read.sh  demo.sh   #在file_read.sh  demo.sh 内查找bash

在目录下查找内容

成功会输出文件名:所有包含内容的行,否则输出为空

需运用-r/-R/-d recurse 选项参数,指明查找路径为目录

$  grep  "bash"   -r  ./   #在当前目录下查找文件内容bash
$  grep  "bash"   -R  ./
$  grep  "bash"   -d recurse  ./

显示查找内容所在行的行号

需运用-n参数,显示行号,可单独也可与其他选项参数写在一起。

$  grep  "bash"  -n  file_read.sh   #在file_read.sh内查找bash 
$  grep  "bash"   -Rn  ./
$  grep  "bash"   -r  -n  ./

反转显示,显示与查找内容不符合的所有内容

需运用-v参数。

$  grep  "bash"   -vn  demo.sh  #显示demo.sh内不包含bash的行,并显示行号


查找以某内容开头的行

需运用正则表达式^...。

$  grep   "^#"   demo.sh  #查找demo.sh内以#开头的行,注意前面不能有空白字符,必须是最开头

查找空白行

需运用正则表达式^...。

需运用正则表达式...$。

$ grep   "^$"    123.txt

查找非指定字符开头的行

$ grep  "^[^#]"  demo.sh   #在demo.sh中查找不以#开头的行

查找以某内容结尾的行

需运用正则表达式...$。

$  grep   "name$"  demo.sh   #查找demo.sh内以name结尾的行,注意必须是最后且后面不能有空白字符

需运用-c参数,不显示详细内容,只显示行数

$ grep "name"  demo.sh  -c   # 在demo.sh中查找name出现的行数

显示查找内容及其前后行内容

需运用 -A 行数/-B 行数/-C 行数 参数

$ grep  "name"  demo.sh  -A  2   #显示查找内容及其后两行内容
$ grep  "name"  demo.sh  -B  2  #显示查找内容及其前两行内容
$ grep  "name"  demo.sh  -C  2  #显示查找内容及其前后两行内容

查找阿拉伯数字


需要用到正则表达式[m]与{n},选项参数-E(指定使用正则表达式)


[]正则表达式:[m]表明查找匹配m字符的内容。


[^m]表明匹配不是m字符的内容。


[m-f]表示匹配m到f的内容,m可以是数字,可以是字符。


{}正则表达式:{m}表示匹配之前的项m次


{m,}表示匹配之前的项至少m次


{m,f}表示匹配之前的项m次到f次。m是可以为0的正整数。

$ grep  "[1-3]\{2\}"  123.txt   #在123.txt中查找1-3之间数字出现两次的内容,注意{}前后一定要加转义字符
$ grep  -E  "[1-3]{2}"  123.txt  #或者直接使用-E参数指定使用正则表达式,则可不加转义
$ grep  "[1-3][1-3]"  123.txt   #与上面相同效果,也表示在123.txt中查找1-3之间数字出现两次的内容
$ifconfig | grep  "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"    

grep用于常规的查询操作固然方便,但是最大的弊端就是查出来不能增删改,导致如果是写一些脚本就会很不方便,这个时候就需要sed和awk这样的工具来实现。


三、sed命令

3.1 sed命令介绍


sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。


命令格式:

sed  [options]  'command'  file(s)
sed  [options]  -f  scriptfile  file(s)

注意:查找的内容前后一定要用/包含起来,示例/sh/  。替换的时候可用@与#替换/。


命令与查找内容可连在一起也可分开,但是中间必须有/作为间隔。


3.2 sed的工作流程

1、sed默认不编辑原文件,而是逐行操作,复制一份到指定内存(pattern space,模式空间)


2、pattern space内进行模式匹配,即和指定条件做匹配


 不满足模式:输出到标准输出STDOUT


 满足模式:进行指定的模式操作,再输出到STDOUT


3、第二个特殊的内存空间 :保持空间(hold space),临时保存操作在另一处内存


4、当执行pattern space和 hold space相关选项时候会进行之间的数据流编辑操作


5、最后根据操作执行hold space空间操作,选择性显示到STDOUT


3.3 选项参数

-c/--copy  用拷贝代替重命名
-e<script>/--expression=<script>   以选项中的指定的脚本来处理输入的文本文件;
-f<script文件>/--file=<script文件>   以选项中指定的脚本文件来处理输入的文本文件;
--follow-symlinks  处理输入的文本文件时,追踪软链接,断开硬链接
-h/--help   显示帮助;
-i[SUFFIX]/ --in-place[=SUFFIX] 就地编辑文件,提供了后缀名(.bak)则备份文件
 -l N/ --line-length=N  为l命令指定换行的长度n
-n/--quiet/——silent   不自动打印模式空间内容,仅显示脚本处理后的结果,sed默认打印全部内容
--posix  禁用所有GNU扩展
-u/ --unbuffered  从输入文件中加载最小的数据并频繁刷新输出缓冲区
-V/--version   显示版本信息。
-r/--regexp-extended 支持使用扩展正则表达式
-s/--separate  把文件作为单独的个体而不是作为单个连续的长流

3.4 命令参数的使用

命令建议用单引号’’或双引号括起来方便区分,多个命令用;隔开。

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末尾。 
! 表示后面的命令对所有没有被选定的行发生作用。  示例:1!表明对文中所有行起作用,3!表示对文中第三行及以下行起作用
= 打印当前行号码。 
# 把注释扩展到下一个换行符以前。 

3.5 替换标记

g 表示行内全面替换。 
p 表示打印行。 
w 表示把行写入一个文件。 
x 表示互换模板块中的文本和缓冲区中的文本。 
y 表示把一个字符翻译为另外的字符(但是不用于正则表达式)
\1 子串匹配标记
& 已匹配字符串标记

3.6 元字符集

^ 匹配行开始,如:/^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/loveloveable/\1rs,loveable被替换成lovers。
& 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
\< 匹配单词的开始,如:/\<love/匹配包含以love开头的单词的行。
\> 匹配单词的结束,如/love\>/匹配包含以love结尾的单词的行。
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的行。

3.7 脚本地址定界

/ 在sed中作为定界符使用,也可以使用任意的定界符:| /
定界符出现在样式内部时,需要进行转义,示例:sed 's/\/bin/\/usr\/local\/bin/g'
不给地址:对全文进行处理
$:表示最后一行
地址范围:
选定行的范围:,(逗号)
/pattern/:被此处模式所能够匹配到的每一行
/pattern/,m:被模式匹配到的第一行起到m行
n,m  表示从n行到第m行
n,+m 表示从n行起往后增加m行
n~m:步进:以n行为基准值,每次增加m行

3.8 组合多个表达式

sed  '表达式' | sed '表达式'
等价于:
sed  '表达式; 表达式'

3.9 常用示例

显示输入文件的行号

需用到命令:=:打印当前行号码(包括空白行)

需用到元字符集:. :匹配一个非换行符的任意字符

需用到命令:!: 表示后面的命令对所有没有被选定的行发生作用。

$ sed   '='  123.txt    #显示文本的每一行行号
$ sed   '3='  123.txt   #显示文本的第三行行号
$  sed  "/./="  123.txt  #只显示非空白行的行号
$ sed -n  "/./!="  123.txt   #只显示空白行行号

显示文件总行数

需用到元字符集:$:匹配到行结束

$ sed   '$='  123.txt  #可显示123.txt内总共有多少行,也就是最后一行的行号

打印输入文件的指定行内容

需用到-n参数:不自动打印,

需用到p命令:打印模块的行

$ sed  -n  '2p'  123.txt   #注意一定要加-n,否则会默认自动打印所有内容
$ sed  -n  '2 p'  123.txt   #注意一定要加-n,否则会默认自动打印所有内容

打印输入文件的指定几行内容

$sed  -n  '2,7 p'  123.txt   #注意一定要加-n,否则会默认自动打印所有内容
$ sed  -n  '2,7p'   123.txt
$ sed  -n  '2,7 {p}'  123.txt  #命令也可单独用{}括起来

替换输入文件中内容

需用到-i参数:就地编辑文件,会对源文件作更改

需用到s命令:替换指定字符,注意字符之间可用/@#隔开,注意如果没有其他命令或者替换标记作为结尾,最后也必须得由它们作为尾字符,

需用到g替换标记:替换行内的所有匹配内容,前面可加数字,表明第几个匹配位置

$ sed  -i  's/bck/sh/'  123.txt  666.txt  #替换123.txt、666.txt内的bck为sh,每行只替换一个
$ sed  -i  's/bck/sh/g'  123.txt   #替换123.txt内的bck为sh,每行都进行全面替换
$ sed  -i  's/bck/sh/3g'  123.txt   #替换123.txt内的bck为sh,从第3个匹配位置开始替换
$ sed  -i  's@bck@sh@g'  123.txt   #替换123.txt内的bck为sh,每行都进行全面替换
$ sed  -i  's#bck#sh#g'  123.txt   #替换123.txt内的bck为sh,每行都进行全面替换

替换输入文件中指定行的内容

$ sed  -i  '1,5 s/bck/sh/g'  123.txt  666.txt  #替换123.txt、666.txt内的第一行到第五行的bck为sh,每行全面替换
$ sed  -i  '2,+2 {s/bck/sh/g}'  123.txt  666.txt  #替换123.txt、666.txt内的第二行往后两行的bck为sh,每行全面替换,命令也可以单独用{}括起来,表示边界
$ sed  -i  '2~2 s/bck/sh/g'  123.txt  666.txt  #替换123.txt、666.txt内的第二行往后每次增加两行的bck为sh,每行全面替换

给文件名\单词前统一替换加前缀或后缀或前后缀


需用到元字符集:^ 匹配行开始,如:/^sed/匹配所有以sed开头的行。


需用到元字符集:$ 匹配行结束,如:/sed$/匹配所有以sed结尾的行。


需用到替换标记:& 已匹配字符串标记,代替之前已匹配内容


需用到正则表达式:\w\+:匹配每一个单词


$ ls | sed  's/^/666_&/g'  #表示给当前文件下的文件名统一添加前缀
$ ls | sed  's/$/666_&/g'  #表示给当前文件下的文件名统一添加后缀
$ ls | sed  's/\w\+/666_&/g'  #表明给所有的单词添加前缀
$ ls | sed  's/\w\+/[&]/'    #表明给每个匹配到的单词用[]括起来

显示指定区间以指定内容开头或结尾的行

需用到元字符集^:匹配行开始

如果/前面有地址定界,则在/外面必须加上{}

$ sed  -n  '1,10 {/^10/p}'  123.txt   #显示123.txt内第1到第10行中以10开头的行
$ sed  -n  '/^10/p'   123.txt        #  /前没有地址定界则可以不加{},如果有则必须加上
$ sed  -n  '1,10 {/sh$/p}'  123.txt   #显示123.txt内第1到第10行中以结尾的行

显示查找内容的所有行、显示找到的第一行及以下指定行

需用到脚本地址定界:/pattern/:被此处模式所能够匹配到的每一行

需用到脚本地址定界:/pattern/,m:被模式匹配到的第一行起到m行

需用到脚本地址定界:$ 匹配到末尾行

$  sed  -n  '/sh/p'  123.txt  #显示123.txt内的所有包含sh的所有行
$  sed  -n  '/sh/ ,$  p'  123.txt   #显示123.txt里第一条包含sh的行及以下到末尾的所有行
$  sed  -n  '/sh/ ,$p'  123.txt   

逆序输出文本内容


需用到命令:!:!前跟非零数字,表示后面的命令对所有没有被选定的行发生作用


需用到命令:G:获得内存缓冲区的内容,并追加到当前模板块文本的后面


需用到命令:h: 拷贝模板块的内容到内存中的缓冲区


需用到命令:d :删除,删除选择的行。


多个命令之前用分号;隔开。

$ sed  '1!G;h;$!d'  123.txt

逆序输出每行内容

$ sed  '/\n/!G;s/..∗\n/&\2\1/;//D;s/.//'  123.txt

删除指定行

需用到命令:d 删除,删除选择的行。

$ grep -n "sh" 123.txt | sed  '4,5d'   #删除grep查找到的内容的第4到5行
$ grep -n "sh" 123.txt | sed  '1,2d'   #删除grep查找到的内容的第1行后每次隔两行删一行
$ sed  '/^$/d'  123.txt     #删除空白行

在指定行前后插入内容

需用到命令:a\ 在当前行下面插入文本。默认当前行为最末行

需用到命令:i\ 在当前行上面插入文本。默认当前行为最末行

需用到命令:c\ 把选定的行改为新的文本。默认当前行为所有行

$ sed  'a\hello\'  123.txt  #在123.txt的末行后增加一行hello
$ sed  'i\hello\'  123.txt  #在123.txt的末行前增加一行hello
$ sed  'c\hello\'  123.txt  #替换123.txt的所有行为hello
$ sed   '8a\hello\'  123.txt   #在123.txt的第8行后增加一行hello
$ sed   '8,10a\hello\'  123.txt  #在123.txt的第8行到10行每一行后增加一行hello
$ sed   '8,10c\hello\'  123.txt  #在123.txt的第8行到10行替换为一行hello

一行内执行多条命令

需用到选项参数-e<script>/--expression=<script>   以选项中的指定的脚本来处理输入的文本文件;

$ sed  -e  '1,5d'  -e  's/sh/bck/'  123.txt     #先删除1到5行再替换sh为bck
$ sed   '1,5d;s/sh/bck/'  123.txt       #三者效果相同
$ sed --expression='1,5d' --expression='s/sh/bck/' 123.txt #三者效果相同

四、awk命令

续集: Linux入门开发: 学习linux三剑客(awk、sed、grep)(下)

目录
相关文章
|
18天前
|
Linux Perl
Linux|从 STDIN 读取 Awk 输入
Linux|从 STDIN 读取 Awk 输入
20 4
|
1月前
|
Linux Perl
Linux技巧|Awk 比较运算符
在 Awk 中,使用比较运算符(如 &gt;, &lt;, ==, != 等)可方便地过滤文本和字符串。本文通过示例展示了如何处理食品购物清单,标记数量小于或等于 20 的商品。 Awk 语法 `expression { actions; }` 用于根据条件执行操作,如在满足条件的行末尾添加特殊标记。例如,`$3 &lt;= 20 { printf &quot;%s\t%s\n&quot;, $0,&quot;TRUE&quot; ; }` 会在数量小于或等于 20 的行后添加 &quot;TRUE&quot;。继续探索 Awk 的比较运算符以进行更复杂的文本处理。
25 2
|
4天前
|
Unix Linux Windows
Linux的学习之路:3、基础指令(2)
Linux的学习之路:3、基础指令(2)
28 0
|
1天前
|
存储 Linux Shell
Linux|Awk 变量、数字表达式和赋值运算符
Linux|Awk 变量、数字表达式和赋值运算符
6 2
|
4天前
|
消息中间件 Unix Linux
Linux的学习之路:17、进程间通信(1)
Linux的学习之路:17、进程间通信(1)
18 1
|
4天前
|
存储 安全 Linux
Linux的学习之路:9、冯诺依曼与进程(1)
Linux的学习之路:9、冯诺依曼与进程(1)
18 0
|
13天前
|
Linux
Linux 指令|date|cal|find|grep|热键
Linux 指令|date|cal|find|grep|热键
|
19天前
|
Linux 应用服务中间件 网络安全
小白学习Linux的学习建议和阶段
【4月更文挑战第5天】小白学习Linux的学习建议和阶段
48 0
|
22天前
|
Linux Perl
Linux| Awk 中“next”命令奇用
Linux| Awk 中“next”命令奇用
26 9
|
1月前
|
算法 Shell Linux
【Shell 命令集合 文档编辑】Linux 文本搜索工具 grep命令使用指南
【Shell 命令集合 文档编辑】Linux 文本搜索工具 grep命令使用指南
30 4