正则表达式是一个字符串,可以用来描述多个字符序列。有几个Linux命令支持使用正则表达式,包括ed、sed、awk、grep,vi也支持但不是所有功能。sed是一种非交互式的流编辑器,可动态编辑文件。这个面向流的编辑器是专门为执行脚本而创建的。可以用来分析关键字的使用、统计等,以及将数据进行替换、删除、选中、选取特定行等功能。提供给它的所有输入都传递到STDOUT,它不会更改输入文件。

1、sed命令数据输入的方式

1)使用管道(|)输入

可以通过管道向其发送数据,使用方式如下,

$ cat /etc/passwd | sed
Usage: sed [OPTION]... {script-other-script} [input-file]...
  -n, --quiet, --silent
                 suppress automatic printing of pattern space
  -e script, --expression = script
...............................

注意cat命令将/etc/passwd的内容通过管道转储到sed的pattern空间。pattern空间是sed用于其操作的内部工作缓冲区。

2)直接从文件中读取数据

sed 从文件中读取数据,而不是通过管道向其发送文件来调用 sed,

例如,

$ sed -e 'd' /etc/passwd

2、sed命令使用的语法

sed [-hnV][-e <script>][-f <script文件>][文本文件]

参数说明:

-e <script>--expression=<script> 以选项中指定的script来处理输入的文本文件。

-f <script文件>--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。

-h--help 显示帮助。

-n--quiet--silent 仅显示script处理后的结果。

-V--version 显示版本信息。

sed命令中script的语法:

/pattern/action

pattern是一个正则表达式,action是下表中给出的命令之一。如果省略pattern,则对每一行执行操作,分隔符/是必需的,不能省略。

命令

说明

p


打印输出行

d

删除行

s/pattern1/pattern2/

将第一次出现的/pattern1替换为pattern2

例如,

删除输入数据中所有行

$ cat /etc/passwd | sed 'd'

例如,

删除输入数据中指定行

命令d前加数据,可以指定要删除的行。

$ cat /etc/passwd | sed '1d' |more
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbi
n/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
mongod:x:997:995:mongod:/var/lib/mongo:/bin/false
--More--
$

d命令之前添加了数字1sed将删除/etc/password的第一行,并打印文件的其余部分。

例如,

删除输入数据中行的范围

从文件中删除多于一行的内容,可以指定删除行的范围,

例如,

$ cat /etc/passwd | sed '1, 8d' |more
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbi
n/nologin
$

'1, 8d'命令将应用于从15的所有行。将删除前五行。

用法如下表,

用法

说明

'3,8d'

3到8行被删除

'5,3d'

只删除了第5行,sed不能反向工作

'4,+5d'

匹配文件中的第4行,删除该行,继续删除接下来的5行,然后停止删除并打印剩余的行

'3,6!d'

除从第3行到第6行以外的所有内容会被删除

'1~3d'

将删除第一行,遍历接下来的三行,然后删除第四行。sed将继续应用此模式,直到文件结束。

'2~2d'

sed删除第二行,步进到下一行,删除下一行,并重复执行,直到文件结束

'4,11p'

打印从第4行到第11行

注意:使用p操作时,应使用-n选项,以避免重复行打印输出行。

例如,

$ cat /etc/passwd | sed -n '4,11p'

3、替换命令

s表示的替换命令将指定的字符串替换其它字符串。并且需要使用分隔符/标识开始和结束的位置。

例如,

将第一次出现adm替换cjavapy:

$ cat /etc/passwd | sed 's/adm/cjavapy/'
daemon:x:2:2:daemon:/sbin:/sbin/nologin
cjavapy:x:3:4:adm:/var/adm:/sbin/nologin
..........................

sed只替换一行中的第一个出现项。如果字符串根在一行中出现多次,则只替换第一个匹配项。

要让sed执行全局替换,需要在命令末尾添加字母g

例如,

$ cat /etc/passwd | sed 's/adm/cjavapy/g'
daemon:x:2:2:daemon:/sbin:/sbin/nologin
cjavapy:x:3:4:cjavapy:/var/cjavapy:/sbin/nologin
..........................

除了g标记之外,还可以传递许多其他有用的标记,可以一次指定多个。

如下表,

标记

说明

g

替换所有匹配,不指定只替换每一次匹配

number

number为数字,只替换第number次匹配

p

会打印输出与替换命令中指定的模式匹配的行。此标记通常与 -n 选项一起使用。

w file

I将缓冲区中的内容写到指定的 file 文件中;

I 或 i

匹配时不区分大小写

M 或 m

除了特殊正则表达式字符^和$的正常行为之外,这个标记还会使^匹配换行符之后的空字符串,以及$匹配换行符之前的空字符串

将分隔符/改为其它字符

如果需要替换的字符串中包含分隔符/,则可以通过在s后面指定一个不同的分隔符。这个是可以自定义的,

例如,

将分隔符/改为;

$ cat /etc/passwd | sed 's;/root;/cjavapy;g'

使用一个空的替换字符串相当于删除

例如,

$ cat /etc/passwd | sed 's/root//g'
:x:0:0::/:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh

可以指定替换的行或范围

例如,

$ cat /etc/passwd | sed '10s/sh/bash/g'

或者

$ cat /etc/passwd | sed '1,5s/sh/bash/g'

可以使用p选项和-n选项打印输出所有匹配的行

例如,

$ cat /etc/passwd | sed -n '/root/p'
root:x:0:0:root user:/root:/bin/sh

4、使用正则表达式

在匹配模式时,可以使用正则表达式,

例如,

删除所有匹配以daemon开头的行

cat /etc/passwd | sed '/^mail/d'

删除所有以sh结尾的行

$ cat /etc/passwd | sed '/sh$/d'

正则表达式中4个常用的元字符:

^:匹配行开头

$:匹配行尾

.:匹配任何单个字符

*:匹配前一个字符的零次或多次出现

[xyx]:字符集合。匹配所包含的任意一个字符。例如,“[apy]”可以匹配cjavapy”中的“p”。

例如,

/a.c/

匹配包含 a+c、a-c、abc、match 和 a3c 等字符串的行

/a*c/

匹配相同的字符串以及诸如 ace、yacc 和 arctic 之类的字符串

/[Cc]javapy/

匹配字符串 Cjavapy 和 cjavapy

/^$/

匹配空行

/^.*$/

匹配整行,无论它是什么

/*/

匹配一个或多个空格

/^$/

匹配空行

1)常用的匹配字符的正则表达式

[a-z]

匹配单个小写字母

[A-Z]

匹配单个大写字母

[a-zA-Z]

匹配单个字母

[0-9]

匹配单个数字

[a-zA-Z0-9]

2)匹配单个字母或数字

GNU sed 中可用字符类关键字,如下表,

括号类

含义

[:alnum:]

字母数字字符

[:alpha:]

字母字符

[:cntrl:]

控制字符

[:digit:]

数字字符

[:graph:]

非空白字符(非空格、控制字符等)

[:lower:]

小写字母

[:print:]

与[:graph:]相似,但是包含空格字符

[:punct:]

标点字符

[:space:]

所有的空白字符(换行符、空格、制表符)

[:upper:]

大写字母

[:xdigit:]

允许十六进制的数字(0-9a-fA-F)

3)使用多个 sed 命令

可以在单个 sed 命令中使用多个 sed 命令,如下所示:

$ sed -e 'command1' -e 'command2' ... -e 'commandN' file

4)使用sed进行分组替换

&:代表整个匹配的字符串

\n:为数字,n为1,则是第一个分组,n为2,则为第二个分组,依此类推。

例如,

输出匹配的分组

$ echo 'N 123 in 456 text' \
| sed -En 's/[^0-9]*([0-9]+)[^0-9]*/\1 /gp'
123 456
$ str='This is a sample 123 text and some 987 numbers'
$ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
123 987
$ echo "cjavapy" | sed -n 's/[[:lower:]]\{7\}/&编程之路/p'
cjavapy编程之路


推荐文档