除换行方法:sed ':a;N;/s/\n//g;ta'
1、sed执行模板=sed '模式{命令1;命令2}'
即逐行读入模式空间,执行命令,最后输出打印出来
2-0、p和P
为方便下面,先说下p和P,p打印当前模式空间内容,追加到默认输出之后(我的机器是之前),P打印当前模式空间开端至\n的内容,并追加到默认输出之前。
sed并不对每行末尾\n进行处理,但是对N命令追加的行间\n进行处理,因为此时sed将两行看做一行。
2-1、n命令
n命令简单来说就是提前读取下一行,覆盖模式空间前一行(并没有删除,因此依然打印至标准输出),如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后的任何命令,并对新读取的内容,重头执行sed。
例子:
从aaa文件中取出偶数行
cat aaa
This is 1
This is 2
This is 3
This is 4
This is 5
sed -n 'n;p' aaa //-n表示隐藏默认输出内容
This is 2
This is 4
注释:读取This is 1,执行n命令,此时模式空间为This is 2,执行p,打印模式空间内容This is 2,之后读取This is 3,执行n命令,此时模式空间为This is 4,执行p,打印模式空间内容This is 4,之后读取This is 5,执行n命令,因为没有了,所以退出,并放弃p命令。
因此,最终打印出来的就是偶数行。
2-2、N命令
N命令简单来说就是追加下一行到模式空间,同时将两行看做一行,但是两行之间依然含有\n换行符,如果命令未执行成功(并非跳过:前端条件不匹配),则放弃之后任何命令,并对新读取的内容,重头执行sed。
例子:
从aaa文件中读取奇数行
cat aaa
This is 1
This is 2
This is 3
This is 4
This is 5
sed -n '$!N;P' aaa
This is 1
This is 3
This is 5
注释中1代表This is 1 2代表This is 2 以此类推
注释:读取1,$!条件满足(不是尾行),执行N命令,得出1\n2,执行P,打印得1,读取3,$!条件满足(不是尾行),执行N命令,得出3\n4,执行P,打印得3,读取5,$!条件不满足,跳过N,执行P,打印得5
2-3、d命令
d命令是删除当前模式空间内容(不在传至标准输出),并放弃之后的命令,并对新读取的内容,重头执行sed。
d命令例子
从aaa文件中取出奇数行
cat aaa
This is 1
This is 2
This is 3
This is 4
This is 5
sed 'n;d' aaa
This is 1
This is 3
This is 5
注释:读取1,执行n,得出2,执行d,删除2,得空,以此类推,读取3,执行n,得出4,执行d,删除4,得空,但是读取5时,因为n无法执行,所以d不执行。因无-n参数,故输出1\n3\n5
2-4、D命令
D命令是删除当前模式空间开端至\n的内容(不在传至标准输出),放弃之后的命令,但是对剩余模式空间重新执行sed。
D命令例子
从aaa文件中读取最后一行
cat aaa
This is 1
This is 2
This is 3
This is 4
This is 5
sed 'N;D' aaa
This is 5
注释:读取1,执行N,得出1\n2,执行D,得出2,执行N,得出2\n3,执行D,得出3,依此类推,得出5,执行N,条件失败退出,因无-n参数,故输出5
2-5、y命令
y命令的作用在于字符转换
y命令例子:
将aaa文件内容大写
sed 'y/his/HIS/' aaa
THIS IS 1
THIS IS 2
THIS IS 3
THIS IS 4
THIS IS 5
此外,如果需要对某个字符串进行大小写转换,则可使用如下方法
cat ddd
This is a and a is 1
This is b and b is 2
This is c and c is 3
This is d and d is 4
This is e and e is 5
sed 's/\b[a-z]\b/\u&/g' ddd
This is A and A is 1
This is B and B is 2
This is C and C is 3
This is D and D is 4
This is E and E is 5
2-6、h命令,H命令,g命令,G命令
h命令是将当前模式空间中内容覆盖至保持空间,H命令是将当前模式空间中的内容追加至保持空间
g命令是将当前保持空间中内容覆盖至模式空间,G命令是将当前保持空间中的内容追加至模式空间
命令例子:
将ddd文件中数字和字母互换,并将字母大写
cat ddd.sed
h
{
s/.*is \(.*\) and .*/\1/
y/abcde/ABCDE/
G
s/\(.*\)\n\(.*is \).*\(and \).*\(is \)\(.*\)/\2\5 \3\5 \4\1/
}
sed -f ddd.sed ddd
This is 1 and 1 is A
This is 2 and 2 is B
This is 3 and 3 is C
This is 4 and 4 is D
This is 5 and 5 is E
注释:读取1,执行h,复制到保持空间,执行s,模式空间得到匹配到的字母a,然后执行y,将a转成A,执行G,追加保持空间内容到模式空间,得
A\nThis is a and a is 1;执行s,重新排列,得出This is 1 and 1 is A;以此类推,得出结果。
这里需要注意的是匹配的内容中,空格一定要处理好,空格处理不对,会造成第二次s匹配错误,无法执行重新排列或排列错误
2-7、x命令
x命令是将当前保持空间和模式空间内容互换
ps:标签用法:
[root@lvs-ser1 ~]# more test
This is a label A
This is a label B
This is a label C
This is a label D
[root@lvs-ser1 ~]# sed '{
/label/b there; \\当匹配label时,就跳转到比标签there那,然后执行下面的s/$/ \!/语句,而s/label/LABEL/;语句就不执行了。
s/label/LABEL/;
:there; \\ 定义一个标签there。
s/$/ \!/}' test
This is a label A !
This is a label B !
This is a label C !
This is a label D !
[root@lvs-ser1 ~]# sed '{
/MM/b there; \\当没有匹配到MM时,就不跳转到there那了,执行下一条s/label/LABEL/语句,以及:there后面的s/$/ \!/语句。
s/label/LABEL/;
:there; \\ 定义一个标签there。
s/$/ \!/}' test
This is a LABEL A !
This is a LABEL B !
This is a LABEL C !
This is a LABEL D !
POSIX字符集
[:alnum:] 文字数字字符
[:alpha:] 文字字符[:digit:] 数字字符
[:graph:] 非空字符(非空格、控制字符)
[:lower:] 小写字符
[:cntrl:] 控制字符
[:print:] 非空字符(包括空格)
[:punct:] 标点符号
[:space:] 所有空白字符(新行,空格,制表符)
[:upper:] 大写字符
[:xdigit:] 十六进制数字(0-9,a-f,A-F)
例子:匹配邮箱,qq和身份证
原文件
匹配结果
说明使用后向引和管道字符的组合时,前面管道取的哪个值,后面后向引用也必须一致 可以匹配com.com不能匹配com.cn
ps:
在Shell中引号分为三种:单引号、双引号和倒引号。
(1)双引号
由双引号括起来的字符,除$、倒引号(`)和反斜线(\)仍保留其特殊功能外,其余字符均作为普通字符对待。“$”表示变量替换,即用其后指定的变量的值来代替$和变量;倒引号表示命令替换;仅当“\”后面的字符是下述字符之一时,“\”才是转义字符,这些字符是:“$”、“`”、“"”、“\”或换行符。转义字符告诉Shell不要对其后面的那个字符进行特殊处理,只是当作普通字符。例如:
QUOTE: |
$ echo "My current dir is `pwd` and logname is $LOGNAME" My current dir is /home/mengqc and logname is mengqc |
(2)单引号
由单引号括起来的字符都作为普通字符出现。例如,
QUOTE: |
$ echo 'The time is ` date ` , the file is $HOME/abc ' The time is ` date ` , the file is $HOME/abc |
(3)倒引号
倒引号括起来的字符串被shell解释为命令行,在执行时,Shell会先执行该命令行,并以它的标准输出结果取代整个倒引号部分。在前面示例中已经见过。例如,
QUOTE: |
$ echo current directory is ` pwd ` current directory is /home/mengqc |
ps2:
LINUX正则表达式(Regular Expression)主要遵从POSIX BRE或者POSIX ERE标准。ERE是BRE的扩展版本,具体更强的处理能力,并增加了一些元字符(metacharactor)。
BRE主要的能力集有:
1) 普通字符(Literal text),如a,b,c等
2)非打印字符,包括TAB,回车,换行,回车换行(WINDOWS)
3)任意字符.
4)字符集,包括单词型字符([[:alnum:]]),非单词型字符([^[:alnum:]]),数字([[:digit:]]),非数字([^[:alnum:]]),空格、TAB、换行等空白字符([[:space:]])以及非空白字符([^[:space:]])
5)边缘匹配符,不管是BRE还是ERE,都只支持匹配行首或行尾,不像perl,还可以匹配单词首和单词尾
6)匹配重复次数(Quantifier/Repetition)
7)分组及后向引用
8)多项匹配(Alteration),使用元字符|,该特性只ERE支持,BRE没有此功能
BRE与ERE似乎对ASCII和UNICODE是否都支持尚待确认;
正前向查找和负前向查找不支持;
正后向查找和负后向查找不支持;
BRE与ERE在能力上区别仅在多项匹配的能力上,其他方面没有大的差别,主要的区别体现在元字符上。
BRE只定义了4组元字符:
[] 用于在多个字符中选定一个字符进行匹配,[]内可以有-以示范围,但-本身不是元字符
. 用于匹配任意字符
^ 用于匹配时表示“非”的含义,还有一个用法是匹配行首
$ 用于匹配行尾
ERE在此基础上增加了3组元字符的定义:
{} 用于表示重复匹配的次数。BRE中只将{}当作普通字符对待,要使用此功能必须加\进行转义,即“\{\}”
() 用于分组。BRE中只将()当作普通字符对待,要使用此功能必须加\进行转义,即“\(\)”
| 完全为ERE新增的多项匹配能力定义的,BRE无多项匹配能力,只将|作普通字符对待