前言 sed命令是一个面向字符流的非交互式编辑器,也就是说sed不允许用户与它进行交互操作。sed是按行来处理文本内容的。在shell中,使用sed来批量修改文本内容是非常方便的。
1. 命令格式
2. 命令参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。 -e :直接在命令列模式上进行 sed 的动作编辑; -f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作; -r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法) -i :直接修改读取的文件内容,而不是输出到终端。 function: a :新增行, a 的后面可以是字串,而这些字串会在新的一行出现(目前的下一行) c :取代行, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行 d :删除行,因为是删除,所以 d 后面通常不接任何参数,直接删除地址表示的行; i :插入行, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行 s :替换,可以直接进行替换的工作,通常这个 s 的动作可以搭配正规表示法,例如 1,20s/old/new/g 一般是替换符合条件的字符串而不是整行 一般function的前面会有一个地址的限制,例如 [地址]function,表示我们的动作要操作的行。下面我们通过具体的例子直观的看看sed的使用方法。
3.删除行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /test.txt 内容如下 11 aa 22 bb 33 cc 23 dd 55 2e sed '1,2d' test.txt 输出: 33 cc 23 dd 55 2e # 其中1,2d中的d表示删除,而d前面的表示删除的行的地址,而1,2表示一个地址范围,也就是删除第1行和第2行; # 地址范围的表示一般是 m,n 表示对m和n行之间的所有行进行操作,也包含第m行和第n行; # sed的地址寻址中可以使用$表示最后一行,例如 m,$ 表示对m行以及其后面的所有行进行操作,包括最后一样;
m,$d就是删除m行以及其后面的所有行内容。
当然我们还可以对某一行进行操作,例如2d表示仅仅删除第2行。
除了使用数字范围 m,n 表示多行区间,以及m表示单行以外,我们还可以使用正则表达式选出符合条件的行,并对这些行进行操作,同样的是上面的文件:
输出: 11 aa 33 cc
上面的命令中 /2/ 是一个正则表达式,在sed中正则表达式是写在 /…/ 两个斜杠中间的,这个正则的意思是寻找所有包含2的行,执行相应的操作,也就是删除所有包含2的行,如果我们只想删除以2开头的行呢,只需要修改一下正则表达式就可以了:
输出: 11 aa 33 cc 55 2e
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@host102442549 opt]# grep "root" /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin -i :忽略大小写(ignore case)。 [root@host102442549 opt]# grep -i "Root" /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin -c :显示总共有多少行被匹配到了,而不是显示被匹配到的内容,注意如果同时使用-cv选项是显示有多少行没有被匹到。 [root@host102442549 opt]# grep -vc "root" /etc/passwd 28 -o :只显示被模式匹配到的字符串。 [root@host102442549 opt]# grep -o "root" /etc/passwd root root root root 如果是多个字符串出现次数,可使用: grep -o ‘objStr1\|objStr2' filename|wc -l #直接用\| 链接起来即可` grep -o '需要匹配的字符串' 文件名 | wc -l 查询文件中 某个字符串出现的次数 grep -o 一条数据里面有多个相同,会统计相同的次数 grep 一条数据里面有多个相同,会统计一次次数 cat localhost_access_log.2017-07-20.txt |grep '/v1/ad?callback='|wc -l 查询当天的请求数
4.模式部分 使用要匹配的字符串 1 直接输入要匹配的字符串,这个可以用fgrep(fast grep)代替来提高查找速度,比如我要匹配一下hello.c文件中printf的个数:fgrep -c "printf" hello.c
使用基本正则表达式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 匹配字符: . :任意一个字符。 [abc] :表示匹配一个字符,这个字符必须是abc中的一个。 [a-zA-Z] :表示匹配一个字符,这个字符必须是a-z或A-Z这52个字母中的一个。 [^123] :匹配一个字符,这个字符是除了1、2、3以外的所有字符。 对于一些常用的字符集,系统做了定义: [A-Za-z] 等价于 [[:alpha:]] [0-9] 等价于 [[:digit:]] [A-Za-z0-9] 等价于 [[:alnum:]] tab,space 等空白字符 [[:space:]] [A-Z] 等价于 [[:upper:]] [a-z] 等价于 [[:lower:]] 标点符号 [[:punct:]] 匹配次数: \{m,n\} :匹配其前面出现的字符至少m次,至多n次。 \? :匹配其前面出现的内容0次或1次,等价于\{0,1\}。 * :匹配其前面出现的内容任意次,等价于\{0,\},所以 ".*" 表述任意字符任意次,即无论什么内容全部匹配。 位置锚定: ^ :锚定行首 $ :锚定行尾。技巧:"^$" 用于匹配空白行。 \b或\<:锚定单词的词首。如"\blike"不会匹配alike,但是会匹配liker \b或\>:锚定单词的词尾。如"\blike\b"不会匹配alike和liker,只会匹配like \B :与\b作用相反。 分组及引用: \(string\) :将string作为一个整体方便后面引用 \1 :引用第1个左括号及其对应的右括号所匹配的内容。 \2 :引用第2个左括号及其对应的右括号所匹配的内容。 \n :引用第n个左括号及其对应的右括号所匹配的内容。
扩展的(Extend)正则表达式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 扩展的(Extend)正则表达式(注意要使用扩展的正则表达式要加-E选项,或者直接使用egrep): 匹配字符:这部分和基本正则表达式一样 匹配次数: * :和基本正则表达式一样 ? :基本正则表达式是\?,二这里没有\。 {m,n} :相比基本正则表达式也是没有了\。 + :匹配其前面的字符至少一次,相当于{1,}。 位置锚定:和基本正则表达式一样。 分组及引用: (string) :相比基本正则表达式也是没有了\。 \1 :引用部分和基本正则表达式一样。 \n :引用部分和基本正则表达式一样。 或者: a|b :匹配a或b,注意a是指 | 的左边的整体,b也同理。比如 C|cat 表示的是 C或cat,而不是Cat或cat,如果要表示Cat或cat,则应该写为 (C|c)at 。记住(string)除了用于引用还用于分组。
5.注意 注1:
1 默认情况下,正则表达式的匹配工作在贪婪模式下,也就是说它会尽可能长地去匹配,比如某一行有字符串 abacb,如果搜索内容为 "a.*b" 那么会直接匹配 abacb这个串,而不会只匹配ab或acb。
注2:
1 所有的正则字符,如 [ 、* 、( 等,若要搜索 * ,而不是想把 * 解释为重复先前字符任意次,可以使用 \* 来转义。
引用:https://www.jb51.net/article/159083.htm https://www.cnblogs.com/chenxiaomeng/p/10066821.html