sed命令总结
正则表达式
正则表达式概述
使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,由普通字符与特殊字符组成,正则表达式广泛使用在脚本编程、文件编辑器中,例如php、java、python、perl、 shell等,正则表达式(regular expression)简写为regex、regexp、RE。用来检索、替换符合模式的文本。具有强大的文本匹配功能,能够在文本中快速高效地处理文本。
在大多数语言中正则表达式都被包括在两个正斜杠(/)之间。例如:/pattern/
正则表达式就是一套为处理大量的字符串而定义的规则和方法,通过正则表达这些特殊符号匹配我们需要的文本,进而我们可以对文本进行增删查改等操作。
为什么要学习正则表达式?
在Linux运维工作中,需要时刻面对大量的日志、程序、命令的输出。迫切的需要过滤我们需要的一部分内容,甚至是一个字符串。例如:只想获取网卡的IP地址信息,从日志中提取我们想需要的信息等。
正则表达式分类
l 基础正则表达式
l 扩展正则表达式
Linux 中常用的文本处理工具
l grep 匹配,查询
l sed 编辑(增加,删除,修改) l awk 文本格式化(字符串提取)
注意事项:
l Linux 中正则一般以行为单位处理文件。
l alias grep ='grep --color=auto'
l 注意字符集,LANG=C
通配符:
正则表达式和我们命令行中使用的通配符是有本质区别的
ls -l *.txt
* 任意长度任意字符串,属于通配符
?单个任意字符串,属于通配符
基础正则表达式
|
\ |
转义字符。例如:“\!”将逻辑否的!看做普通字符 |
|
^ |
匹配字符串开始的位置,以…为开头的 |
|
$ |
匹配字符串结束的位置,以…结束的 |
|
^$ |
表示空行,不是空格 |
|
. |
匹配任意的一个字符 |
|
* |
匹配前面子表达式(字符)0 次或者多次 |
|
.* |
匹配任意字符串 |
|
[list] |
匹配 list 列表中的一个字符,例如:[abc]、[a-z]、[a-zA-Z0-9] |
|
[^list] |
匹配任意非 list 表中的一个字符,例如:[^a-z]、[^0-9]、[^A-Z0-9] |
|
\{n\} |
匹配前面子表达式 n 次 |
|
\{n,\} |
匹配前面子表达式至少 n 次 |
|
\{n,m\} 匹配前面子表达式最少 n 次,最大 m 次 \< 固定词首 \> 固定词尾 |
|
常见的转义字符
|
转义字符 |
意义 |
|
\a |
响铃(BEL) |
|
\b |
退格(BS),将当前位置移到前一列 |
|
\n |
换行(LF)将当前位置移到下一行开头 |
|
\r |
回车(CR)将当前位置移动到本行开头 |
|
\t |
水平制表(HT)调到下一个 TAB 位置 |
|
\v |
垂直制表(VT) |
|
\\ |
代表一个反斜杠字符“\” |
扩展正则表达式
扩展正则表达式是基础正则表达式的扩充深化
+ 匹配前面子表达式 1 次以上
? 匹配前面子表达式 0 次或者 1 次
() 将括号中的字符串作为一个整体
| 以或的方式匹配字符串
文本流编辑器-sed
sed 是一个非交互式的流编辑器(stream editor),常用于读取文本内容或根据指定的条件进行处理,可实现增删改查的功能。被广泛应用于 shell 脚本,以完成自动化处理任务。
sed 依赖于正则表达式。
sed 在使用时通常会指定行号或正则表达式,否则处理的是全文。
工作原理: sed 每次只从文件或标准输入中读取一行数据,将之拷贝到一个编辑缓冲区,然后对该行数据按指定命令进行处理,并将结果输出到屏幕(标准输出),接着读入下一行。整个文件处理过程像流水线一样逐行处理。
Sed 默认并不直接修改文件,他只是操作编辑缓冲区中的信息,编辑完的信息默认在屏幕上显示,如果有需要可将采用重定向的方式导出到指定的文件中(或者结合“-i”选项直接在文件中修改。)
格式:
sed [选项] ‘编辑命令’ 输入文件 shell 命令 | sed [选项] ‘编辑命令’
sed [选项] –f sed 脚本文件 输入文件
常用选项:
-e 指定要执行的命令,只有一个编辑命令时可省略
-n 只输出处理后的行,读入时不显示,不对原文件进行修改
-i 直接编辑原文件,不输出结果
-f 从脚本文件中读取编辑命令并执行
编辑命令格式:
/[地址 1[,地址 2]]/操作 [参数]
地址:可为行数、正则表达式、$,没有地址代表全文
操作:
p 打印(输出) d 删除(整行) s 替换(字符串) c 替换(整行) r 读取指定文件(到行后)
= 显示文件行号
a append,追加指定内容到行后 i insert,追加指定内容到行前 w 另存为 n 表示读入下一行内容
H 复制到剪贴板 g 将剪贴板中的内容覆盖到指定行
G 将剪贴板中的内容追加到指定行后
练习案例:
|
[root@localhost ~]# nl test.txt 1 gd 2 god 3 good 4 goood 5 gooood 6 gold 7 glad 8 gaad 9 abcDfg 10 food 11 601151272 12 HELLO 13 010-6666888 14 0666-5666888 15 IP 192.168.1.108 16 IP 173.16.16.1 17 pay $180 |
l p 打印输出第 12 行内容 [root@localhost ~]# sed -n '12p' test.txt
HELLO
输出 3~5 行的内容
[root@localhost ~]# sed -n '3,5p' test.txt good goood gooood
输出所有奇数行
|
[root@localhost ~]# sed -n 'p;n' test.txt gd good gooood glad abcdEfg 60115127Z 010-66668888 IP 192.168.1.108 pay $180 |
输出所有偶数行
[root@localhost ~]# sed -n 'n;p' test.txt god goood gold gaad food HELLO
0666-5666888
IP 173.16.16.1
输出 1~5 行之间的奇数行(第 1,3,5 行)
[root@localhost ~]# sed -n '1,5{p;n}' test.txt gd good gooood
输出包含字母 H 的行
[root@localhost ~]# sed -n '/H/p' test.txt
HELLO
输出所有包含大写字母的行
[root@localhost ~]# sed -n '/[A-Z]/p' test.txt abcDfg HELLO
IP 192.168.1.108
IP 173.16.16.1
输出最后一行
[root@localhost ~]# sed -n '$p' test.txt pay $180
l d 删除(整行)删除第 16 行
|
[root@localhost ~]# sed '16d' test.txt gd god good goood gooood gold glad gaad abcDfg food 601151272 HELLO 010-6666888 0666-5666888 IP 192.168.1.108 pay $180 |
删除空行
|
[root@localhost ~]# sed -i '/^$/d' test.txt [root@localhost ~]#cat test.txt gd god good goood gooood gold glad gaad abcdEfg food 60115127Z |
HELLO
010-66668888
0666-5666888
IP 192.168.1.108 IP 173.16.16.1 pay $180
删除第 1 行和第 3 行
[root@localhost ~]# sed -e '1d' -e '3d' test.txt god goood gooood gold glad
同样,删除第 1 行和第 3 行
[root@localhost ~]# sed -e '1d;3d' test.txt god goood gooood gold glad
l s 替换(字符串)
将所有小写 o 替换为大写 O(g 表示若同一行有多个小写 o,全部替换,若不加 g,则只替换每行的第一个小写 o)
|
[root@localhost ~]# sed 's/o/O/g' test.txt gd gOd gOOd gOOOd gOOOOd gOld glad gaad abcdEfg fOOd 60115127Z HELLO 010-66668888 0666-5666888 IP 192.168.1.108 IP 173.16.16.1 pay $180 |
以 IP 开头的行,行首加上#
|
[root@localhost~]# sed '/^IP/ s/^/#/' test.txt gd god good goood gooood gold glad gaad abcdEfg food 60115127Z HELLO 010-66668888 0666-5666888 #IP 192.168.1.108 #IP 173.16.16.1 pay $180 |
在每行行尾插入字符串 EOF
|
[root@localhost ~]# sed 's/$/EOF/' test.txt gdEOF godEOF goodEOF gooodEOF goooodEOF goldEOF gladEOF gaadEOF abcdEfgEOF foodEOF 60115127ZEOF HELLOEOF 010-66668888EOF 0666-5666888EOF IP 192.168.1.108EOF IP 173.16.16.1EOF pay $180EOF |
将/etc/passwd 文件 20~25 行的/sbin/nologin 替换为/bin/bash。如果用 s///的形式,将会多
次使用转义符\,我们可以使用其他符号,如@进行分隔
[root@localhost ~]# sed '20,25 s@/sbin/nologin@/bin/bash@' /etc/passwd
l c 替换(整行)将第 2 行替换为 AAAAAAA
|
[root@localhost ~]# sed '2cAAAAAAAAAAAAAAA' test.txt gd AAAAAAAAAAAAAAA good goood gooood gold glad gaad abcDfg food 601151272 HELLO 010-6666888 0666-5666888 IP 192.168.1.108 IP 173.16.16.1 pay $180 |
把第 5 行至最后一行的内容替换为两行,AAAAAA…和 BBBBBBB…(\n 为换行)
[root@localhost ~]# sed '5,$cAAAAAAAAAAA\nBBBBBBBBBBBB' test.txt gd god good goood
AAAAAAAAAAA
BBBBBBBBBBBB
l r 读取指定文件(到行后)
读取/etc/resolv.conf 文件内容在第 5 行后
|
[root@localhost ~]# sed '5r /etc/resolv.conf' test.txt gd god good goood gooood # Generated by NetworkManager nameserver 202.106.0.20 nameserver 8.8.8.8 gold glad |
|
gaad abcDfg food 601151272 HELLO 010-6666888 0666-5666888 IP 192.168.1.108 IP 173.16.16.1 pay $180 |
l a 追加指定内容到行后在第 2 行后添加 NNNN
[root@localhost ~]# sed '2aNNNNNNNNNNNNNNNNNN' test.txt gd god
NNNNNNNNNNNNNNNNNN
good
……
在所有带数字的行下追加====…
|
[root@localhost ~]# sed '/[0-9]/a==============' test.txt gd god good goood gooood gold glad gaad abcDfg food 601151272 ============== HELLO 010-6666888 ============== 0666-5666888 ============== IP 192.168.1.108 ============== IP 173.16.16.1 ============== pay $180 |
==============
l i 追加指定内容到行前在第 2 行前追加 NNNNN…
[root@localhost ~]# sed '2iNNNNNNNNNNNNNNNNNN' test.txt gd
NNNNNNNNNNNNNNNNNN
god
……
l w 另存为将 15~16 行内容另存到 out.txt 文件中
[root@localhost ~]# sed '15,16w out.txt' test.txt
[root@localhost ~]# cat out.txt
IP 192.168.1.108
IP 173.16.16.1
l H 复制到剪贴板 l G 将剪贴板中的内容追加到指定行后将包含字母 IP 的行剪切到最后一行下
|
[root@localhost ~]# sed '/IP/ {H;d};$G' test.txt gd god good goood gooood gold glad gaad abcdEfg food 60115127Z HELLO 010-66668888 0666-5666888 pay $180
IP 192.168.1.108 IP 173.16.16.1 |
将 1~5 行内容复制到 15 行、16 行下
[root@localhost ~]# sed '1,5H;15,16G' test.txt gd
|
god good goood gooood gold glad gaad abcdEfg food 60115127Z HELLO 010-66668888 0666-5666888 IP 192.168.1.108
gd god good goood gooood IP 173.16.16.1
gd god good goood gooood |
分组,调用
[root@CentOS6-node1 ~]# cat httpd.conf
#ServerName www.example.com:80
[root@CentOS6-node1 ~]# sed -n 's/#\(ServerName www.\)example\(.com:80\)/\1baidu\2/gp' httpd.conf
ServerName www.baidu.com:80
分组调用练习
获取 IP 地址:
[root@localhost ~]# ifconfig eth0 |sed -n '/inet addr/s/.*r://gp' | sed -n 's/B.*//gp'
192.168.200.101
[root@localhost ~]# ifconfig eth0 | sed -n '2 s#.*r:\(.*\)B.*#\1#gp'
192.168.200.101
[root@localhost ~]# ifconfig eth0 | sed -nr '2 s#.*r:(.*)B.*#\1#gp'
192.168.200.101
|
通过 sed 打印文件第 1 列和第 7 列 [root@localhost ~]# head -5 /etc/passwd | sed -r 's/(.*):x.*:(.*)/\1 \2/g' root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin lp /sbin/nologin
1.使用 sed 获取/etc/passwd 文件第一列和第 7 列。 sed -n "1,5 s#:.*:# #gp" /etc/passwd sed -nr '1,5s#(.*):x.*:(.*)#\1 \2#gp' /etc/passwd
2.使用 sed 获取/etc/passwd 文件前 5 行的最后一个字符。 sed -n "1,5 s#.*\(.\)#\1#p" /etc/passwd sed -nr '1,5 s#(.)#\1 #gp' /etc/passwd | awk '{print $NF}' for i in $(head -5 /etc/passwd |rev); do echo $i | head -c1;echo ; done head -5 /etc/passwd | rev |while read line ; do echo $line | head -c1;echo ; done |
sed & 引用方式:
[root@localhost ~]# sed -n '1,12 s#root#&admin#gp' /etc/passwd rootadmin:x:0:0:rootadmin:/rootadmin:/bin/bash operator:x:11:0:operator:/rootadmin:/sbin/nologin

浙公网安备 33010602011771号