在文本处理的世界里,SED流编辑器宛如一把瑞士军刀,功能强大且实用。无论是处理海量数据文件,还是批量修改配置文件,SED都能展现出其独特的魅力。今天,就让我们一同深入探索SED的奇妙世界,掌握其基础知识和实用技巧,让文本处理变得轻松自如。
一、SED:文本处理的神器
(一)SED是什么
SED是一款流编辑工具,专门用于对文本进行过滤与替换工作。它能够以一种高效且灵活的方式处理文本,尤其适用于大规模文本文件的操作。例如,当你面对几十个配置文件需要进行统一修改时,SED就能发挥巨大作用,让你在短时间内完成任务。
(二)SED的工作流程
- 读取文件:SED通过文件或管道读取文件内容,每次仅读取一行,这使得它在处理大数据文件时不会占用过多内存,保证了处理效率。
- 模式空间操作:读取的内容会被复制到缓冲区,也就是模式空间(pattern space)。在这里,SED根据指令对内容进行处理。
- 输出结果:处理后的结果默认输出至标准输出,即屏幕上。如果需要,也可以将结果保存到文件中。
以下是SED工作流程的示意图:
输入
------------------------------------------------
|
|
v
读取一行内容,并复制到模式空间 <------------ sed指令
|
|
v
------------------------------------------------
输出经过处理后的内容二、SED基本语法:开启文本处理之旅
(一)基本语法格式
sed Options... [script] [inputfile...]
其中,Options是SED程序本身的选项,用于控制SED的行为;script是脚本指令,用于指定对文件内容的操作;inputfile是输入文件,如果没有指定,则SED默认对标准输入进行处理(如键盘输入)。
(二)常用选项解析
- 显示版本和帮助
- --version:显示SED版本。
- --help:显示帮助文档。
 
- 控制输出
- -n,--quiet,--silent:静默输出,屏蔽SED程序自动打印模式空间内容的功能。
 
- 执行脚本指令
- -e script:允许多个脚本指令被执行。
- -f script-file, --file=script-file:从文件中读取脚本指令,方便编写自动脚本程序。
 
- 修改源文件(谨慎使用)
- -i,--in-place:直接修改源文件,处理后的内容将覆盖源文件内容。
 
- 其他选项
- -l N, --line-length=N:指定- l指令输出的行长度,- l指令用于输出非打印字符。
- --posix:禁用GNU SED扩展功能。
- -r, --regexp-extended:在脚本指令中使用扩展正则表达式。
- -s, --separate:控制SED对多个文件名的处理方式。
- -u, --unbuffered:最低限度缓存输入与输出。
 
(三)简单案例演示
- 
追加与插入 
 假设我们有一个名为test.txt的文件,内容如下:DEVICE=eth0 
 ONBOOT=yes
 BOOTPROTO=static
 IPADDR=192.168.0.1
 NETMASK=255.255.255.0
 GATEWAY=192.168.0.254
- 在第二行后添加TYPE=Ethernet:
            
            
              bash
              
              
            
          
          sed '2a TYPE=Ethernet' test.txt- 在第三行前添加TYPE=Ethernet:
            
            
              bash
              
              
            
          
          sed '3i TYPE=Ethernet' test.txt- 替换
 将文件中所有的yes替换为no:
            
            
              bash
              
              
            
          
          sed's/yes/no/g' test.txt- 删除
 删除第3至4行的内容:
            
            
              bash
              
              
            
          
          sed '3,4d' test.txt- 使用正则表达式定位操作行
- 匹配到包含ONBOOT的行,并在其后添加TYPE=Ethernet:
            
            
              bash
              
              
            
          
          sed '/ONBOOT/a TYPE=Ethernet' test.txt- 匹配以GATEWAY开始的行,并删除该行:
            
            
              bash
              
              
            
          
          sed '/^GATEWAY/d' test.txt- 
从脚本文件中读取指令 
 创建一个名为sed.sh的脚本文件,内容如下:/^$/d 
这条指令的作用是删除空白行。然后执行:
            
            
              bash
              
              
            
          
          sed -f sed.sh test.txt- 执行多个指令的方法
- 使用分号隔开指令:
            
            
              bash
              
              
            
          
          sed's/yes/no/;s/static/dhcp/' test.txt- 使用-e选项:
            
            
              bash
              
              
            
          
          sed -e's/yes/no/' -e's/static/dhcp/' test.txt- 利用分行指令:
            
            
              bash
              
              
            
          
          sed '
s/yes/no/
s/static/dhcp/' test.txt三、正则表达式:精准定位文本
(一)确定操作地址
- 行号指定
- number:指定输入文件的唯一行号,如- 2d表示删除第二行。
- first~step:以- first开始,操作步长为- step,如- 1~2表示打印文件的奇数行。
- $:匹配文件的最后一行。
 
- 正则表达式匹配
- /regexp/:通过正则表达式匹配操作地址,例如- /ONBOOT/匹配包含- ONBOOT的行。
- \cregexpc:匹配扩展正则表达式,- c字符可以使用任意字符替代。
 
- 范围指定
- addr1,addr2:匹配从操作地址- 1到操作地址- 2的所有行,如- 2,8d删除2至8中间的所有行。
- addr1,+N:匹配地址- 1以及后面的- N行内容。
 
(二)正则表达式概述
- 字符匹配
- char:字符本身匹配字符本身,如- /abc/定位包含- abc的行。
 
- 数量限定符
- *:匹配前面表达式出现了0或若干次,如- /a*/可以找到- a、- aa、- aaa等。
- \+(扩展正则表达式):匹配前面表达式的1次或多次。
- \?(扩展正则表达式):匹配前面表达式的0次或1次。
- \{i\}:匹配前面表达式的- i次(- i为整数),如- a\{3\}找到- aaa。
- \{i,j\}:匹配前面表达式的- i到- j次,如- a\{1,2\}找到- a或- aa或- aaa。
- \{i,\}:匹配前面表达式至少- i次。
 
- 分组与引用
- ():将内的模式存储在保留空间,最多可存储9个独立子模式,可通过转义- \1至- \9重复保留空间的内容。
 
- 其他元字符
- .(点):匹配任意字符。
- ^:匹配行的开始,如- ^test匹配所有以- test开始的行。
- $:匹配行的结尾,如- test$匹配所有以- test结尾的行。
- []:匹配括号中的任意单个字符,如- a[nt]匹配- an或- at。
- [^]:匹配不包含在- []中的字符,如- [^a-z]匹配除- a-z以外的字符。
- \n:匹配换行符。
- \char:转义特殊字符,如- \*匹配字面意义上的星号。
 
四、SED脚本指令:实现多样化操作
(一)注释(#)
注释行以#开始,如果#后面的字符为n,则屏蔽SED程序的自动输出功能,等同于命令选项-n。
(二)替换(s)
- 基本格式
 [address]s/pattern/replacement/flags
 其中,address为操作地址,s为替换指令,/pattern/匹配要替换的内容,/replacement/为替换的内容,flags可以是:- n(1至512之间的数字):表示对模式空间中指定模式的第- n次出现进行替换。
- g:对模式空间的匹配进行全局更改,没有- g则仅第一次匹配被替换。
- p:打印模式空间的内容。
- w file:将模式空间的内容写到文件- file中。
 
- 示例
 假设有一个名为test.txt的文件,内容如下:
            
            
              html
              
              
            
          
          <html>
<title>First Web</title>
<body>Hello the World! <body>
</html>将样本文件中的第二个<body>替换为</body>。
编写sed.sh脚本如下:
/body/{
s//\/body/2
}执行sed程序:
            
            
              bash
              
              
            
          
          sed -f sed.sh test.txt结果为:
            
            
              html
              
              
            
          
          <html>
<title>First Web</title>
<body>Hello the World!</body>
</html>(三)删除(d)
删除指令删除匹配的行,且会改变SED脚本中命令的执行顺序。因为匹配的行被删除后,模式空间变为"空",SED脚本后续命令不再执行,而是读取新的输入行,从头开始执行命令。
(四)追加(a)
在匹配行后追加内容。例如,对于文件test.txt:
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
NETMASK=255.255.255.0
GATEWAY=192.168.0.254执行sed '/static/a IPADDR=192.168.0.1' test.txt,会在包含static的行后添加一行IPADDR=192.168.0.1。
(五)插入(i)
在匹配行前插入内容。如sed '/NETMASK/i IPADDR=192.168.0.1' test.txt,会在包含NETMASK的行前添加一行IPADDR=192.168.0.1。
(六)更改(c)
更改匹配行的内容。例如,sed '/ONBOOT/c ONBOOT=yes' test.txt会将包含ONBOOT的行(整行)替换为ONBOOT=yes。
(七)列印(l)
显示模式空间中的内容,显示非打印字符,一般与-n一起使用,否则会输出两次。例如,sed -n '1,2l' test.txt会显示文件的第一、二行内容及换行符(以$表示)。
(八)转换(y)
按字符进行转换。例如,对于文件test.txt:
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
netmask=255.255.255.0
GATEWAY=192.168.0.254编写sed.sh脚本:
/.*/{
/netmask/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
}执行sed -f sed.sh test.txt,会将netmask中的小写字母转换为大写字母。
(九)打印(p)
作用类似于l,但不显示非显示字符,一般与-n配合使用。如sed -n '1,2p' test.txt仅显示第一、二行内容。
(十)读写文件(r,w)
- 
读取文件(r) 
 [line-address]r file,例如,有name.txt和mail.txt两个文件:
 name.txt内容:Jacob 
 Tom
 Jerry
mail.txt内容:
jacob@gmail.com
tom@gmail.com
jerry@gmail.com编写sed.sh脚本:
/.*/{
$r mail.txt
}执行sed -f sed.sh name.txt,会在name.txt文件末尾添加mail.txt的内容。
- 写入文件(w)
 [address]w file,可以将指定行的内容写入到文件中。
(十一)退出(q)
匹配地址后退出SED脚本。例如,sed '10q' test.txt会打印文件前10行内容后退出。
(十二)下一步(n)
[address]n,输出模式空间中的内容,然后读取输入的下一行。例如,对于文件name.txt:
Jacob
Tom
Jerry编写sed.sh脚本:
/.*/{
n
/.*/d
}执行sed -f sed.sh name.txt,会删除偶数行,结果为:
Jacob
Jerry(十三)Next(N)
多行Next(N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后,来创建多行模式空间。模式空间的最初内容与新的输入行之间用换行符分隔。例如,对于文件test.txt:
111
222
222
333编写sed.sh脚本:
#n
/222/{
N
l
}执行sed -f sed.sh test.txt,结果如下:
222\n222(十四)Print(P)
多行打印(P)与打印(p)稍有不同,该命令仅输出多行模式空间中的第一部分,直到第一个插入的\n换行符为止。例如,对于文件test.txt:
111
222
333
444
555
666编写不同的sed.sh脚本并执行,结果如下:
- 
脚本1: /.*/{ 
 N
 }
结果:
111
222
333
444
555
666- 
脚本2: /.*/{ 
 N
 l
 }
结果:
111\n222$
111
222\n333$
222
333\n444$
333
444\n555$
444
555\n666$
555
666- 
脚本3: /.*/{ 
 N
 P
 }
结果:
111
111
222
222
333
333
444
444
555
555
666
666- 
脚本4: /.*/{ 
 N
 p
 }
结果:
111
222
111
222
333
444
333
444
555
666
555
666(十五)Delete(D)
删除命令(D)删除模式空间中直到第一个插入的换行符(\n)前的这部分内容,它不会读入新的输入行,并返回SED脚本的顶端,使得剩余指令继续应用于模式空间中剩余的内容。
(十六)Hold(h,H),Get(g,G)
模式空间用于存放当前输入行,还有一个保持空间(hold space)。可以使用以下命令在两者之间移动数据:
- Hold(h|H):将模式空间的内容复制或追加到保持空间。
- Get(g|G):将保持空间的内容复制或追加到模式空间。
- Exchange(x):交换保持空间与模式空间的内容。
例如,对于文件test.txt:
1
2
11
22
111
222编写sed.sh脚本:
/1/{
h
d
}
/2/{
G
}执行sed -f sed.sh test.txt,结果为:
2
1
22
11
222
111(十七)branch,test
分支(b)和测试(t)命令用于控制SED脚本的执行流程。分支命令是无条件转移,测试命令用于有条件转移,测试只有当替换命令改变当前行成功时才会执行。标签是任意不多于7个字符的序列,以冒号开始,如:mylable。在分支或测试命令
作者:代老师的编程课
如果你喜欢本文,请长按二维码,关注 Java码界探秘
.