详解Shell脚本:sed命令工具 ,awk命令工具

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解Shell脚本:sed命令工具 ,awk命令工具相关的知识,希望对你有一定的参考价值。

-----------------------------概述-----------------------------------

Linux文本处理工具(以下都是命令和工具,而且只是作为展示,不能作为修改动作)

grep(过滤,但是不支持正则表达式)
egrep(支持正则表达式)
sed (行过滤)
awk(列过滤)

-

正则表达式概念

正则表达式:使用单个字符串来描述、匹配一系列符合某个句法规则的字符串

由普通字符与特殊字符组成,一般用在脚本编程、文本编辑器中,如php、python、she等,简写为regex、regexp、 用来检索、替换符合模式的文本,具有强大的文本匹配功能

能够在文本海洋中快速高效地处理本文

-

正则表达式层次:

1基础正则表达式
2扩展正则表达式

-

正则表达式:就是查找字符串匹配的规律

比如邮箱的格式:[email protected]

比如手机号码:1 [356789][0-9]{10}
第一位数不变 [第二位数内范围]

比如人的年龄 :[0-1] {1} [0-2] [0-9] | [0-9] {2}
[ 匹配的范围 ] { 匹配的次数 }

--------------基础正则表达式元字符----------

基础正则表达式是常用的正则表达式部分

非打印字符:

非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符描述

  • cx 匹配由x指明的控制字符。例如, cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 ‘c‘ 字符。
  • f 匹配一个换页符。等价于 x0c 和 cL。
  • 匹配一个换行符。等价于 x0a 和 cJ。
  • 匹配一个回车符。等价于 x0d 和 cM。
  • s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ f v]。注意 Unicode 正则表达式会匹配全角空格符。
  • S 匹配任何非空白字符。等价于 [^ f v]。
  • 匹配一个制表符。等价于 x09 和 cI。

  • v 匹配一个垂直制表符。等价于 x0b 和 cK。

-

特殊字符:

所谓特殊字符,就是一些有特殊含义的字符,如上面说的 runoob 中的 ,简单的说就是表示任何字符串的意思。如果要查找字符串中的 符号,则需要对 进行转义,即在其前加一个 : runo*ob 匹配 runo*ob。

许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符 放在它们前面。下表列出了正则表达式中的特殊字符:

特别字符描述

  • $ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘ ‘ 或 ‘ ‘。要匹配 $ 字符本身,请使用 $。
  • ( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。
  • 匹配前面的子表达式零次或多次。要匹配 字符,请使用 *。
    • 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。
  • . 匹配除换行符 之外的任何单字符。要匹配 . ,请使用 . 。
  • [ 标记一个中括号表达式的开始。要匹配 [,请使用 [。
  • ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 ?。
  • 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n‘ 匹配字符 ‘n‘。‘ ‘ 匹配换行符。序列 ‘‘ 匹配 "",而 ‘(‘ 则匹配 "("。
  • ^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 ^。
  • { 标记限定符表达式的开始。要匹配 {,请使用 {。
  • | 指明两项之间的一个选择。要匹配 |,请使用 |。

-

限定符:

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 * 或 + 或 ? 或 {n} 或 {n,} 或 {n,m} 共6种。

正则表达式的限定符有:

字符描述

  • 匹配前面的子表达式零次或多次。例如,zo 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
    • 匹配前面的子表达式一次或多次。例如,‘zo+‘ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
  • ? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。
  • {n} n 是一个非负整数。匹配确定的 n 次。例如,‘o{2}‘ 不能匹配 "Bob" 中的 ‘o‘,但是能匹配 "food" 中的两个 o。
  • {n,} n 是一个非负整数。至少匹配n 次。例如,‘o{2,}‘ 不能匹配 "Bob" 中的 ‘o‘,但能匹配 "foooood" 中的所有 o。‘o{1,}‘ 等价于 ‘o+‘。‘o{0,}‘ 则等价于 ‘o*‘。
  • {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。‘o{0,1}‘ 等价于 ‘o?‘。请注意在逗号和两个数之间不能有空格。

-

举例说明:

[[email protected] ~]# vim test01.sh
gd
god
good
goood
gooood
gold
glad
gaad
abcEfg
food
12345678Z
888-88888888
6666-6666666
IP 192.168.120.5
IP 119.75.217.109
pay $888

[[email protected] ~]# sed -n ‘/$/p’ test01.sh 
pay $888

[[email protected] ~]# awk ‘/$/’ test01.sh 
pay $888

[[email protected] ~]# grep  ‘$’ test01.sh 
pay $888

[[email protected] ~]# grep "^[a-z]" test01.sh                          #### 以字母开头

[[email protected] ~]# sed -n ‘/^[a-z]/p’ test01.sh                             #### 以字母开头 

[[email protected] ~]# grep ‘[0-9]$’ test01.sh                              #### 以数字结尾

[[email protected] ~]# grep ‘go.d’ test01.sh 
good
gold

-

常见元字符(续)

   *   :匹配前面子表达式0次或者多次

例: good、go.d

例: [abc]、[a-z]、[a-z0-9]

例:[^a-z]、[^0-9]、[^A-z0-9]

{n,m}:匹配前面的子表达式n到m次,有{n}、{n,}、{n,m}三种格式
例:go{2}d、go{2,3}d、go{2,}d

-

举例说明:


[[email protected] ~]# grep ‘goo*d’ test01.sh 
god
good
goood
gooood

[[email protected] ~]# grep "go[la]d" test01.sh 
gold

[[email protected] ~]# sed -n ‘/go[la]d/p’ test01.sh 
gold

[[email protected] ~]# awk ‘/go[la]d/’ test01.sh 
gold

[[email protected] ~]# grep ‘[0-9]{3,4}-[0-9]{7,8}’ test01.sh 
888-88888888
6666-6666666

[[email protected] ~]# grep ‘[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}’ test01.sh 
IP 192.168.120.5
IP 119.75.217.109

-

### PS:
### egrep ‘go{2}d’           
 #这样形式的命令出现时一定要加 ‘ ‘  ,       一般在命令中出现   { } 这两个个符号时,最好都加 ‘ ‘【命令不识别再去掉后使用也行】

-

-----------------扩展正则表达式--------------

扩展正则表达式是对基础正则表达式的扩充深化

扩展元字符

+:匹配前面子表达式1次以上
例:go+d,将匹配至少一个0
?:匹配前面子表达式0次或者1次
例:go?d,将匹配gd或god

举例说明:

[[email protected] ~]# grep go+d test01.sh      #不支持扩展
[[email protected] ~]# egrep go+d test01.sh 
god
good
goood
gooood

[[email protected] ~]# awk ‘/go+d/’ test01.sh 
god
good
goood
gooood

[[email protected] ~]# sed -n ‘/go+d/p’ test01.sh #不支持扩展

[[email protected] ~]# awk ‘/go?d/’ test01.sh 
gd
god

扩展元字符(续)

() : 将括号中的字符串作为一个整体
例:(xyz)+,将匹配xyz整体1次以上,如xyzxyz

| : 以或的方式匹配字条串
例1: good food,将匹配good或者food
例2: g(oo|la)d,将匹配good或者glad
举例说明:
[[email protected] ~]# egrep ‘g(oo)+d’ test01.sh
good
gooood

[[email protected] ~]# egrep ‘g(la|aa)d’ test01.sh
glad
gaad

[[email protected] ~]# egrep -v ‘#|^$|^:’ /etc/ssh/sshd_config

----------------------------------sed 工具-----------------------------

sed工具概述:

sed是文本处理工具,读取文本内容,根据指定的条件进行处理如删除、替换、添加等

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

-

sed命令格式:
命令语法
sed -e ‘编辑指令’ 文件1 文件2………
sed -n -e ‘编辑指令’ 文件1 文件2………
sed -i -e ‘编辑指令’ 文件1 文件2………

-

常用选项
-e 指定要执行的命令,只有一个编辑命令时可省略
-n 只输出处理后的行,读入时不显示
-i 直接编程文件,而不输出结果

-

编辑命令格式
[地址1[,地址2]操作[参数]

"地址",可数字、正则表达式、$,没有地址代表是所有行

"操作",可以是p、d、s、r、w、i等

-

sed命令:

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

"参数",一般有g,代表只要符合条件的全部进行处理

-

sed元字符集:
^: 匹配行开始,如:/^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/(love)able/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的行。

-

sed用法举例:

删除举例
sed ‘3,5d’ bfile #删除第3~5行
sed ‘/xml/d’ bfile #删除包含xm的行
sed ‘/^install/d’ bfle #删除以 instal开头的行
sed ‘/arch$/d’ bfle #删除以arch结尾的行
sed ‘$d’ bfile #删除最后一行
sed ‘/^$/d’ bfle #删除所有的空行

-

举例说明:


[[email protected] ~]# vim test01.sh 
     1        gd
     2        god
     3        good
     4        goood
     5        gooood
     6        gold
     7        glad
     8        gaad
     9        abcEfg
    10        food
    11        12345678Z
    12        888-88888888
    13        6666-6666666
    14        IP 192.168.120.5
    15        IP 119.75.217.109
    16        pay $888

[[email protected] ~]# sed -n ‘12p’ test01.sh 
888-88888888

[[email protected] ~]# sed -n ‘3,5p’ test01.sh 
good
goood
gooood

[[email protected] ~]# sed -n ‘p;n’ test01.sh #打印奇数行
gd
good
gooood
glad
abcEfg
12345678Z
6666-6666666
IP 119.75.217.109

[[email protected] ~]# sed -n ‘n;p’ test01.sh #打印偶数行
god
goood
gold
gaad
food
888-88888888
IP 192.168.120.5
pay $888

[[email protected] ~]# sed -n ‘1,5{p;n}’ test01.sh #输出1~5行之间的奇数行
gd
good
gooood

[[email protected] ~]# sed -n ‘$p’ test01.sh #打印最后一行
pay $888

[[email protected] ~]# sed -n -e ‘1p;10p’ test01.sh #输出第1、10行
gd
food

[[email protected] ~]# sed ‘16d’ test01.sh  #删除16行,不对文本进行操作
gd
god
good
goood
gooood
gold
glad
gaad
abcEfg
food
12345678Z
888-88888888
6666-6666666
IP 192.168.120.5
IP 119.75.217.109

[[email protected] ~]# cat -n test01.sh            #查看多了几行空行

[[email protected] ~]# sed -i ‘/^$/d’ test01.sh      #直接对文本操作,删除空白行

-

替换举例:

sed ‘s/xml/XML/’bfile// #将每行中的第一个xml替为XML
sed ‘s/xml//g’bfle/ #将文件中的所有xml删除
sed ‘3,5s/xml/XML/g’ bfile/ #将第3~5行中的所有xml都替换为ⅩML
sed ‘/xml/s/com/COM/g’ bfile// #将包含xml的所有行中的com都替换为COM

-

举例说明
[[email protected] ~]# sed ‘/^IP/ s/^/#/’ test01.sh #匹配IP,并并且开头添加成#

[[email protected] ~]# sed ‘11 s/$/ ABC/’ test01.sh #在11行行尾添加ABC

[[email protected] ~]# sed ‘5,10 s/$/ ABC/’ test01.sh #在5-10行行尾添加ABC

[[email protected] ~]# sed ‘/^abcd/ s/$/ ABC/’ test01.sh #以abcd开头的行尾添加ABC

-

多次执行编辑命令
sed -e ‘3,5p’ -e ‘3,5s/xml/XML/g’ bfile
可将多个编辑命令保存到文件中,通过-f指定文件,以完成多个处理操作

举例说明:
[[email protected] ~]# sed ‘2cABC’ test01.sh #将第二行替换成ABC
[[email protected] ~]# sed ‘2aABC’ test01.sh #将第二行插入ABC

[[email protected] ~]# sed ‘5r /proc/version’ test01.sh #在第五行下追加

[[email protected] ~]# sed ‘2iABC123’ test01.sh #在第二行加入ABC123

[[email protected] ~]# sed ‘15,16w out.txt’ test01.sh #把当前15~16行保存到当前目录out.txt

[[email protected] ~]# sed ‘/^IP/{H;d};$G’ test01.sh #将以IP开头的两行剪切到最后一行,H代表复制

[[email protected] ~]# sed ‘1,5H;15,16G’ test01.sh #将1~5进行复制,15粘贴一次,16行粘贴一次

--------------awk工具介绍------------------

awk也是一个功能强大的编辑工具,与sed一样,可在无交互的情况下实现相当复杂的文本操作

命令格式

awk 选项 ‘模式或条件{编辑指令}’文件1 文件2
awk -f 脚本文件 文件1 文件2

工作原理

逐行读取文本,默认以空格为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令

-

举例说明:

[[email protected] ~]# vim 6.txt
11 22 33 44
55 66 77 88

[[email protected] ~]# awk ‘{print $1}’ 6.txt
11
55

[[email protected] ~]# awk ‘{print $1"---"$3}’ 6.txt
11---33
55---77

[[email protected] ~]# sed -i ‘s/ /:/g’ 6.txt #空格加:
[[email protected] ~]# cat 6.txt
11:22:33:44:
55:66:77:88:

[[email protected] ~]# awk -F’:’ ‘{print $3}’ 6.txt #第三列以":"分隔
33
77

-

awk内置变量:

FS:指定每行文本的字段分隔符,缺省为空格或制表位(-F)
NF:当前处理的行的字段个数
NR:当前处理的行的行号(序数)
$0:当前处理的行的整行内容
$n:当前处理行的第n个字段(第n列)

-

举例说明:

[[email protected] ~]# awk -F’:’ ‘{print $3,NF}’ 6.txt
33 5
77 5
[[email protected] ~]# cat 6.txt
11:22:33:44: #最后一个 :认为还是有参数,行的字段个数是5
55:66:77:88:

[[email protected] ~]# awk -F’:’ ‘{print NR,$3,NF}’ 6.txt
1 33 5
2 77 5

[[email protected] ~]# awk ‘{print $0}’ 6.txt
11:22:33:44:
55:66:77:88:

-

awk工具举例:

打印文本内容
awk ‘NR==1NR==3{ print}’ bfile #输出第1至第3行内容
awk ‘NR==1|NR==3{ print} bfile #输出第1行、第3行内容
awk ‘/^root/{print’/etc/ passwd #输出以root开头的行

按字段输出文本

awk ‘{print $1,$3}’ bfile #输出每行中的第1、3字段
awk -F ":" ‘{print $1,$7}’ /etc/shadow #输出密码为空的用户的shadow记录

-

举例说明:

[[email protected] ~]# awk ‘NR==1,NR==3{print}’ test01.sh
gd
god
good

[[email protected] ~]# awk ‘(NR>=1) && (NR<=3){print}’ test01.sh #打印第一行到第三行
gd
god
good

[[email protected] ~]# awk ‘NR==1 || NR==3{print}’ test01.sh #打印第一行、第三行
gd
good

[[email protected] ~]# awk ‘(NR%2)==0{print}’ test01.sh #输入偶数行

[[email protected] ~]# awk ‘(NR%2)==1{print}’ test01.sh #输入奇数行

[[email protected] ~]# awk ‘/^I/’ test01.sh #以大写I开头的行

[[email protected] ~]# awk -F’:’ ‘$2==""{print $1}’ /etc/shadow #密码是空的

[[email protected] ~]# awk -F’:’ ‘{print $1,$3,$4,$7}’ /etc/passwd

[[email protected] ~]# free -m | awk ‘/cache:/’
/+ buffers/cache: 71 925
[[email protected] ~]# free -m | awk ‘/cache:/{print $3+$4}’

[[email protected] ~]# free -m | awk ‘/cache:/{print int($3/($3+$4)*100)}’ #int取整数,并不是四舍五入
6

以上是关于详解Shell脚本:sed命令工具 ,awk命令工具的主要内容,如果未能解决你的问题,请参考以下文章

sed && awk工具 及一些常用的shell脚本

shell脚本——正则表达式Sed与Awk文本处理工具详解

shell中执行sed命令

sed &amp;&amp; awk工具 及一些经常使用的shell脚本

shell脚本之awk工具的使用

linux awk命令详解