sed的分组用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sed的分组用法相关的知识,希望对你有一定的参考价值。

参考技术A

在sed 启用扩展正则表达式之后,通常更多的配合分组功能进行使用,这时候需要注意的内容如下:
A . 启用sed 的扩展正则表达式的方法是使用 -r 参数
B . 启用扩展正则表达式之后,小括号是可以自动识别为“分组的分割符号”,也就是说小括号不是普通的字符;
C . \\s 表示空格或者tab 键, 而 * 表示任意个数的字符,? 表示0 或者一个字符,+ 表示一个或者多个字符,而 . 表示任意字符
D . 启用分组以后,在对分组进行引用的时候,用 \\1, \\2 之类的表示方式,其中 \\1就是小括号引用起来的第一个分组,依次类推,可以使用很多个分组
E . 在使用分组的时候,最常见的一种情形是:确认每个分组匹配的长度,这个遵循的一个重要原则是: .* 组合的长度取决于前面的组合以及后面的组合, .* 本身无法确定所匹配的字符串; 那么,如果要把 .* 作为分组的最后一部分怎么办呢,那这时候,其右边的边界就是 结束符号 $.
F . 在sed 启用扩展正则表达式后,中括号 和大括号并不是作为普通字符看待,所以如果要把中括号, 大括号识别为普通字符,那么需要加上反斜杠;

G :
如果使用sed的替换功能来修改文件的某一行,那么要对一整行进行匹配,尽量不做只匹配部分内容的操作,否则可能会导致出现问题,而要对一整行做一个完整匹配,就离不开使用分组功能,特别是 .* 以及 \\s 的使用. 而 最好避免使用 .*\\s 作为边界,因为容易发生匹配错误的情况,如果非要使用不可,那么一定要做好验证
H :
如果匹配的时候,某一个分组匹配到空,那么后续的分组将都会是空,这一点在调试的时候特别有用,记得哦

使用sed分组方法进行匹配,从而输出想要的内容
在这个例子中,我想要输出system-auth 这个pam配置文件中调用了pam_succeed_if.so模块,并且包含有condition的那个配置项的内容,而pam_succeed_if.so 模块的condition 是通过中括号进行限定的,所以就是找出: 含有pam_succeed_if.so 并且含有中括号的配置项. 具体可以用如下的分组方式:

其实对于上述的需求在实际的工作中极少使用sed来实现,sed 更多的用于文件的修改,和上述的分组方法类似,正在阅读的你是否get到了呢?

sed的基本用法和高级用法

sed 的详细用法

sed:stream editor 流编辑器
sed的工作模式;sed是一个行文本编辑器,默认每次处理文本中所匹配到一行内容到模式空间,然后用后面的命令进行操作,操作完成之后,会把模式空间
里面的内容实现在屏幕上,然后把模式空间的中的内容删除,同时把下一行所匹配到内容读入模式空间

为了下面演示方便,我们创建一个文本文件a.text

#cat a.text
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

sed 命令的语法格式:

sed [options] ‘addresscommand‘ file (1)
sed [options] -f scriptfile file (2)

(2)是sed的脚本用法后面会介绍到
先介绍语法(1)种用法:**


address(匹配的条件)的表示法:

linenumber:指定特定行号
startline,endline:指定起始行号,和结束行号
linenumber,+N :N数字,表示从指定行号向后N行
/patten/:以正则表达式的匹配模式
/patten1/,/patten2/:从模式匹配1到模式匹配2


options:选项

-n 静默模式 常使用p命令时会用
-i 改变原文件
-f file 跟脚本文件
-e 可以执行多个命令语句


command:命令(简单用法)

p:打印模式空间中行
d:删除,删除选择的行
r file:读取file中的内容追加到匹配的行后面
R file:读取file中的内容的第一行追加到匹配行的后面
w file:将匹配到的行,保存到file中
W file:将匹配到的行的第一行,保存到file中
a string 在当前行下面插入文本。
i string 在当前行上面插入文本。
! 表示后面的命令对所有没有被选定的行发生作用.
y 和s用法类似,但只能替换大小写
s/patten/string/ 把patten匹配到的换成string字符


sed替换标记:

g表示全局替换
1表示前面第一个左括号所表示的内容,2表示前面第二个左括号中表示的内容,以此类推
&表示前面匹配到的内容


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的行。

下面我们看例子:

address 匹配条件的用法

1,只显示a.text中的2行

[email protected]:~# sed -n ‘2p‘ a.text 
ce xx xx tom xx rhce xx tom xx

注意,我们也里面要用到-n 选项,如果不用-n 静默模式的话,
它会显示全部内容(这是sed的默认动作,可以看一下工作模式),匹配到的内容会显示两遍

2,删除a.text 中2-4行

[email protected]:~# sed "2,4d" a.text 
zz xx tom xx tom rhce xx rh
yyyy rhce yyyyy 

3,上面删除a.text中2-4行,也可以这样表示

[email protected]:~# sed "2,+2d" a.text 
zz xx tom xx tom rhce xx rh
yyyy rhce yyyyy 

4,删除以x开头的行。

[email protected]:~# sed "/^x/d" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
yyyy rhce yyyyy 

5,删除a.text中以第一个zz开头的行到第一个xx开头的行结束。

[email protected]:~# sed "/^zz/,/^xx/d" a.text
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

command 命令的用法

1,i string 的用法,在a.text中ce开头的行前面追加 i love linux 的新行

[email protected]:~# sed "/^ce/i i love linux" a.text   
zz xx tom xx tom rhce xx rh
i love linux
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

2,a string 的用法和i string 类似 在a.text中ce开头的行后面追加i love linux 的新行

[email protected]:~# sed "/^ce/a i love linux" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
i love linux
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

3,r file的用法,把/etc/fstab 追加到a.text中含有y的行。

root[email protected]:~# sed "/.*y.*/r /etc/fstab" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 
/etc/fstab: static file system information.
<file system> <mount point>   <type>  <options>   <dump>  <pass>
/ was on /dev/sda1 during installation
UUID=d12e3f89-049d-45c1-8b31-3a1cf551585f /   ext4    errors 0       1
swap was on /dev/sda5 during installation
UUID=07308ec5-870b-46f0-b983-ebc2a56fb0f2 none  swap    sw   0       0
/dev/sr0  /media/cdrom0   udf,iso9660 user,noauto     0       0

4,w file 的用法,把a.text中含有tom的行,保存到/root/b.text

[email protected]:~# sed "/tom/w /root/b.text" a.text
[email protected]:~# cat b.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 

5,s/patten/string/的使用。把a.text 中第一个tom换成jerry .

[email protected]:~# sed "s/tom/jerry/" a.text 
zz xx jerry xx tom rhce xx rh
ce xx xx jerry xx rhce xx tom xx 
xx xx jerry xx rhce xx xx 
xxx xxx jerry rhce xx xx 
yyyy rhce yyyyy 

提示;sed默认只替换第一个匹配到的patten.如果想替换只替换第二tom为jerry
这时替换标记就用作用了
这条命令可以这样写:sed "s/tom/jerry/2" a.text 以此类推。可以替换想要替换的,

如果要想替换全部的可以写成
sed "s/tom/jerry/g" a.text

[email protected]:~# sed "s/tom/jerry/g" a.text
zz xx jerry xx jerry rhce xx rh
ce xx xx jerry xx rhce xx jerry xx 
xx xx jerry xx rhce xx xx 
xxx xxx jerry rhce xx xx 
yyyy rhce yyyyy

&和1的用法,&和1的相同之处,和不同点
把she like my love 中 like和love后面都加上一个r.变成she liker my lover

[email protected]:~# echo "she like my love" | sed "s/l..e/&r/g"
she liker my lover

注释,&表示前一个/patten/中的内容

[email protected]:~# echo "she like my love" | sed  "s/(l..e)/1r/g"
she liker my lover

可以用分组的方法来实现后向引用。

如果把she like my love 中like和love中的l变成L。变成she Like my Love

[email protected]:~# echo "she like my love" | sed  "s/l(..e)/L1/g"
she Like my Love

这样的只能用分组来实现。不能用&来引用。

sed的高级用法

command:命令、

=:显示行号
n:读取匹配模式的行的下一行到模式空间中.注:模式空间中匹配模式的行被删除。
N:读取匹配模式的行,和匹配模式行的下一行。
h 拷贝模板块的内容到内存中的缓冲区。如果原来缓冲区有内容被覆盖
H 追加模板块的内容到内存中的缓冲区。
g 获得内存缓冲区的内容,并替代当前模板块中的文本。
G 获得内存缓冲区的内容,并追加到当前模板块文本的后面

高级command的用法

1,= 的用法。显示以ce开头的是第几行。

[email protected]:~#  sed "/^ce/=" a.text 
zz xx tom xx tom rhce xx rh
2
ce xx xx tom xx rhce xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

2,n 的用法。把zz开头的行,下一行中的tom全部换成TOM

[email protected]:~# sed "/^zz/{n;s/tom/TOM/g}" a.text
zz xx tom xx tom rhce xx rh
ce xx xx TOM xx rhce xx TOM xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

3,N的用法,把zz开头的行和下一行中的rhce全部换成RHCA.

[email protected]:~# sed "/^zz/{N;s/rhce/RHCA/g;s/rh
ce/RH
CA/}" a.text 
zz xx tom xx tom RHCA xx RH
CA xx xx tom xx RHCA xx tom xx 
xx xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy 

首先,要用N读取zz开头的行和它的下一行,可以看到zz行的结尾处rh和ce开头的行是两行,
用s/rhce/RHCA/g不会被替换。所以我们还要s/rh ce/RH CA/来替换。

如果我们使用多行模式,^就不是表示行的开头,而是模式空间里的开头,$也不是行的结尾了,而是行的结尾

[email protected]:~# sed "/^xx/{N;s/^xx/qq/g}" a.text 
zz xx tom xx tom rhce xx rh
ce xx xx tom xx rhce xx tom xx 
qq xx tom xx rhce xx xx 
xxx xxx tom rhce xx xx 
yyyy rhce yyyyy

分析:如果不是模式空间的开头,那么下面两个xx也会被替换成qq.

h和G的用法:
我们新建一个文本b

#cat b
a
b
aa
bb

4,通过模式空间和保持空间的转化实现的效果

[email protected]:~# sed "/a/{h;d};/b/G" b
b
a
bb
aa

sed [options] -f scriptfile file (2)
通常通过脚本对文件批量处理;
如一个文件中需要多出用sed 修改可以使用脚本
脚本文件格式为:‘addresscommand‘
‘addresscommand‘
......

以上是关于sed的分组用法的主要内容,如果未能解决你的问题,请参考以下文章

用 sed 对数字进行分组:下划线对我不起作用

linux文本处理sed软件包管理磁盘存储文件系统和挂载

正则表达式中分组功能高级用法

mysql中的分组统计函数及其用法实例

Stream Collectors.groupingBy的四种用法 解决分组统计(计数求和平均数等)范围统计分组合并分组结果自定义映射等问题

mysql分组用法