Chinaunix首页 | 论坛 | 博客
  • 博客访问: 139340
  • 博文数量: 37
  • 博客积分: 2671
  • 博客等级: 少校
  • 技术积分: 335
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-11 13:18
文章分类

全部博文(37)

文章存档

2011年(16)

2010年(21)

我的朋友

分类:

2011-01-26 20:10:46

1):awk基本控制语句

$1==lead {
printf "\t%s\n",$2
}

$1!=lead {
printf "%s\n",$1
printf "\t%s\n",$2
lead=$1
}

其实也就是模式和命令的格式,即[pattern] {command}。

2):基本的元字符与扩展的元字符

grep与sed使用基本的正则元字符,awk与egrep使用扩展的。

3):*在正则表达式中和普通shell中的区别

[root@oracle ForVMC]# echo h*
h1 h2 h3 h4

下面是正则式中的*号含义:

[root@oracle ForVMC]# wc -l m
4 m
[root@oracle ForVMC]# cat m
h1
h2
h3
h4

[root@oracle ForVMC]# sed -n '/^h.*$/p' m --只要以h开头就行
h1
h2
h3
h4
[root@oracle ForVMC]# sed -n '/^h*$/p' m --行中有任一多的h,包括空行
--这里没有显示行


.和*是基本的正则式(BRE)元素。

4):基本的元字符(BRE)


. 配置除换行符以外的任一字符,但是不能配置换行符(awk中可以)。    ------awk部分


*匹配任一多个在它前面的字符


[]字符类:
[,]与-在[]中的匹配 :
[root@oracle ForVMC]# cat m
]hello-
[root@oracle ForVMC]# grep '^[]cd].*[ba-]$' m
]hello-
[root@oracle ForVMC]# grep '^[]cd].*[-ba]$' m
]hello-
[root@oracle ForVMC]# cat m
[hello-
[root@oracle ForVMC]# grep '^[[cd].*[-ba]$' m
[hello-
就是说如果[,]和-在[]元字符中(些时这两个符号在[]中都有特殊含义),要想把这三个当成是[]成员,则只可以将[,]放在[]最前-放在最后。
匹配[或者]:
[root@oracle ForVMC]# cat m
[hello-.
]yes
[root@oracle ForVMC]# grep '^[][]' m
[hello-.
]yes
另外,所有其它的元字符如果被放在了[]中都将失去元字符的特殊含义,而表示其字面值。
[root@oracle ForVMC]# cat m
[hello-.
]yes
[root@oracle ForVMC]# grep '[.]$' m --这里.被当成字面值
[hello-.
[]在awk中也匹配换行符                                                                  ------awk部分

^脱字节,如果不是在[]中就表示行的开始,在[]表示不在[]范围内的。          
^在awk中也匹配嵌入的换行符            -------awk部分


$匹配行的结尾
awk中是匹配"字符串"的结尾,即使字符串中有嵌入的换行符     ------awk部分
[root@oracle ForVMC]# cat m
[hello-.
]yes
[root@oracle ForVMC]# grep '\.$' m
[hello-.
[root@oracle ForVMC]# grep '[.]$' m
[hello-.


\{n,m\} 匹配n-m次
记住m是有最大值限制的,可以通过getconf查看相应的最大值。
[root@oracle ForVMC]# cat m
ccababee
mmabdd
[root@oracle ForVMC]# grep '\(ab\)\{2\}' m
ccababee

\是转义符号,也就是转义以上所有的特殊元字符为其字面值。
[root@oracle ForVMC]# cat m
$
^
.
*
[root@oracle ForVMC]# sed -n '/^\$/p;/^\^/p;/^\./p;/^\*/p' m
$
^
.
*


BRE特殊字符汇总:

. ,[] 匹配字符范围
*,\{n,m\}匹配它前面字符次数
^,$行的头和尾
\(\)正则分组,适用于BRE

三类:范围,次数,行头与行尾


5):扩展的元字符(ERE),awk egrep(grep -E)专用

+ 至少一次,*是至少0次
[root@oracle ForVMC]# cat m
ymmoo
ymoo
yoo
[root@oracle ForVMC]# egrep '^ym+o*$' m
ymmoo
ymoo
普通的grep是不能使用+的:
[root@oracle ForVMC]# grep '^ym+o*$' m
[root@oracle ForVMC]# grep -E '^ym+o*$' m --grep -E=egrep,fgrep=grep -F
ymmoo
ymoo


? 匹配0次或者1次(助记:0?还是1?)
[root@oracle ForVMC]# cat m
mmoo
ymoo
[root@oracle ForVMC]# grep -E '^y?' m
mmoo
ymoo

| 关系或
同样用上面的例子
[root@oracle ForVMC]# grep -E '^y|m?' m
mmoo
ymoo

() 对正则表达式分组
{n,m} 用于POSIX的egrep和POSIX的awk,而不是传统的egrep和awk
[root@oracle ForVMC]# cat m
llmmmmtt
lnmmmll
[root@oracle ForVMC]# gawk -W posix '/(mm){2}/ {print $0}' m
llmmmmtt
--gawk -W posix 启动awk 的posix兼容模式

分类:

+,?次数
| (就两种选择),POSIX的{n,m} 范围
() 正则分组,适用于ERE

6): BRE与ERE一点语法比较

[root@oracle ForVMC]# cat m
llmmmmtt
lnmmmll
[root@oracle ForVMC]# sed -n '/\(mm\)\{2\}/p' m
llmmmmtt
[root@oracle ForVMC]# gawk '/\(mm\)\{2\}/ {print $0}' m
[root@oracle ForVMC]# sed -n '/\(mm\)\{2\}/p' m
llmmmmtt
[root@oracle ForVMC]# gawk '/\(mm\)\{2\}/ {print $0}' m
[root@oracle ForVMC]# gawk -W posix '/\(mm\)\{2\}/ {print $0}' m
[root@oracle ForVMC]# gawk -W posix '/(mm){2}/ {print $0}' m
llmmmmtt

当前结论:\(\) \{\}(扩展字符)对应() {}(基本元字符)

匹配():

[root@oracle ForVMC]# cat m
ll(mm)(mm)tt
lnmmmll
[root@oracle ForVMC]# gawk -W posix '/(\(mm\)){2}/ {print $0}' m
ll(mm)(mm)tt

sed不可以用\来转义,但是可以用[]来转义
[root@oracle ForVMC]# sed -n '/\(\(mm\)\)\{2\}/p' m
[root@oracle ForVMC]# sed -n '/\([(]mm[)]\)\{2\}/p' m
ll(mm)(mm)tt


7):实践

\\转义自己:
[root@oracle ForVMC]# cat m
\hello
[root@oracle ForVMC]# sed -n '/\\hello/p' m
\hello

intel处理器匹配:

[root@oracle ForVMC]# cat m
8086
80686
80386
80586
[root@oracle ForVMC]# egrep '80[[:digit:]]?86' m
8086
80686
80386
80586


8):形式化的字符类--POSIX

[:alnum:] 字母和数字
[:digit:] 数字
[:alpha:] 字母
[:xdigit:] 十六进制数
[:lower:] [:upper:]
[:punct:]

以上是常用的

[:blank:] 匹配空格和TAB符
[root@oracle ForVMC]# cat m
[root@oracle ForVMC]# sed 'l' m --sed的l参数可以显示出不可打印字符
\t $

\t是制表符,空格没有显示出来$代表行尾

[:graph:] 匹配可见的,不包括空格

[:space:] 空白字符
[:print:] 可打印的,包括空格


[root@oracle ForVMC]# egrep 'h[[:space:]]+e' m
h   e
[root@oracle ForVMC]# egrep 'h[[:print:]]+e' m
h   e
[root@oracle ForVMC]# egrep 'h[[:graph:]]+e' m


9):单词的匹配

基本正则式(ERE)\<\>的使用

[root@oracle ForVMC]# cat m
hellbookyy
hello books yy
hello book mm
book yy
[root@oracle ForVMC]# sed -n '/\/p' m
hello book mm
book yy
[root@oracle ForVMC]# egrep '\' m
hello book mm
book yy
[root@oracle ForVMC]# awk '/\/ {print $0}' m
hello book mm
book yy


其实\<\>就是字(word)单位的标识,就像vi可以以字为单位移动一样。

10):TAB与空格的匹配

[root@oracle ForVMC]# cat m
\t
\space
[root@oracle ForVMC]# sed -n '/^\t/p' m
\t
[root@oracle ForVMC]# sed -n '/^ /p' m
\space

\把t的字面值转义成了制表符。

显示行后的空格:

[root@oracle ForVMC]# sed -n 's/ *$/$$/p' m
\space$$

11):awk中的^和$            --awk部分


12):号码格式化

[root@oracle ForVMC]# cat m
05506141423
[root@oracle ForVMC]# sed -n 's/\([[:digit:]]\{4\}\)\([[:digit:]]\{7\}\)/\1-\2/p' m
0550-6141423

13):逻辑或

[root@oracle ForVMC]# cat m
Unix
UNIX
UniX
[root@oracle ForVMC]# egrep 'Unix|UNIX|UniX' m
Unix
UNIX
UniX
[root@oracle ForVMC]# sed -n '/Unix/p;/UNIX/p;/UniX/p' m
Unix
UNIX
UniX


14):正则分组

[root@oracle ForVMC]# cat m
Unix System
Unix
[root@oracle ForVMC]# sed -n '/Unix\( System\)\{0,1\}/p' m
Unix System
Unix
[root@oracle ForVMC]# egrep 'Unix( System)?' m
Unix System
Unix
 
1):注释#
#n代表sed -n

[root@oracle ~]# cat m
Moon
make
[root@oracle ~]# cat sedscr
#n this is a comment
s/m/l/gp
[root@oracle ~]# sed -f sedscr m
lake

2):替换命令的详细语法

[address]s/pattern/replacement/flag

其中flag可选项:

n 值范围1-512 --指定第起次出现
p --打印模式空间
W file --将模式空间的内容写到file中
g   --全局标志

替换命令的定界符可以使用除了换行符外所有字符:

[root@oracle ~]# cat m
Moon
make
[root@oracle ~]# sed -n 's^m^o^p' m
oake
[root@oracle ~]# sed -n 's|m|o|p' m
oake


replacement部分只有下面的内容才具有特殊意义,其它的一切都只有字面含义:

& 引用pattern本身
\n 匹配第n个串,和正则分组\( \)或者ERE的()配合使用
\ 转义符,通常只转义\本身,&和换行符

[root@oracle ~]# sed -n 's!\(Mo\)\(on\)!"\1"\2!p' m
"Mo"on
[root@oracle ~]# sed -n 's!\(Mo\)\(on\)!"\1"\ --这里用来转义换行
> \2!p' m
"Mo"
on

综上:sed 的replacement部分特殊的元字符也只有& \ \n三个,其中在\n中n的范围是1-9

3):指定替换第几个,s命令n的作用

[root@oracle ~]# sed -n 'l;s/\t/TAB/2p' m
\t\tMoon$
TABMoon
make$

4):\n回调正则分组

[root@oracle ~]# cat m
abcdefg
[root@oracle ~]# sed -n 's/\(a\)\(b\)\(c\)\(d\)\(e\)\(f\)\(g\)/\1-\2-\3-\4-\5-\6-\7/p' m
a-b-c-d-e-f-g


5):删除命令d

删除后,模式空间将被清空,所以删除后的命令将不在工作,而是读入下一行。

[root@oracle ~]# cat m
abcdefg
[root@oracle ~]# sed -n 's/a/o/p;/^o/d;p' m
obcdefg


6):追加插入和更改

a(append),i(insert),c(change)

语法:
[address] command\
text

插入是在模式空间前加入内容,追加是在模式空间后,更改是将模式空间内容替换掉。

[root@oracle ~]# sed '/^a/i\
hello' m
hello
abcdefg
[root@oracle ~]# sed '/^a/a\
hello' m
abcdefg
hello


理解a的工作方式:

[root@oracle ~]# cat m
abcdefg

[root@oracle ~]# sed -n '/^a/a\
hello
p
' m

abcdefg
hello


[root@oracle ~]# fc
sed -n '/^a/a\
hello
p
s/h/t/gp' m

abcdefg
hello    --只有两行,也就是说hello是在对模式空间运用完所有的命令后,才附加到标准输出内容中的


[root@oracle ~]# fc
sed -n '/^a/a\
hello
p
s/a/t/gp' m

abcdefg
tbcdefg --这一行并不是hello,因为还有命令在处理当前的模式空间
hello    --最后附加到标准输出中的

所以可以将a理解为优先级很低的运算符,它通常是最后处理的,不管他出现在什么地方。

i插入也一样:

[root@oracle ~]# sed -n '/^a/i\
> hello
> p
> s/h/t/gp' m
hello
abcdefg

[root@oracle ~]# fc
sed -n '/^a/i\
hello
p
a\
world
s/h/t/gp
s/w/m/gp' m

hello
abcdefg
world

c更改命令更加特殊,它将会把模式空间的内容代替并输出,且运行c命令后模式空间将被清空(这一点和d命令一样),所以它后续的命令都不起作用了。

[root@oracle ~]# sed -n '/^a/c\
why why why' m
why why why

从上面的结果我们还可以得出一个结论:c命令总是包含一个隐匿打印命令,所以可以把c命令理解为:清空模式空间内容并打印给定字符串。

再回过头看看a和i,其实和c一样,不管你有没有指定p命令,它总是输出所指定的内容的:

[root@oracle ~]# sed -n '/^a/a\
> yes' m
yes

7):列表命令l

[root@oracle ~]# cat m


[root@oracle ~]# sed -n 'l' m
\t\t\t\t$
\t\t\t\t$

l命令可以显示出非可见![[:graph:]]字符。

上面的例子中,m中有两行TAB符,第行4个。

8):替换命令y,类似于shell命令tr

[root@oracle ~]# cat m
abcde
[root@oracle ~]# sed -n 'y/abcde/ABCDE/;p' m
ABCDE


9):打印命令p

主要就是一下:普通的打印命令和作为s替换打印命令的区别。
普通打印就是无条件的打印当前模式空间中的内容,而替换命令中的打印命令必须是s成功发生后再执行。

10):打印行号

[root@oracle ~]# sed -n '/^.*/=' m
1
2
3

类似于awk的NR(Row Number)
[root@oracle ~]# gawk '{print NR " " $0}' m
1 abcde
2 ddeed
3 oommt

且只要你在地址后给出了等号,就一定打印行号,不管你有没有指定p命令。
 
 
 
1):n(next)命令
工作模式:打印当前模式空间内容,并清空后立即读入下一行,且读入下一行后不返回命令头,而是继续应用后面的命令。

[root@localhost ~]# cat m
aaaaa
bbbb
[root@localhost ~]# sed -n '/^a/n;s/b/m/gp' m
mmmm

[root@localhost ~]# sed '/^a/n;s/b/m/g' m
aaaaa
mmmm

如果没有指定-n选项,n操作前先打印当前行。

[root@localhost ~]# sed -n 's/b/m/gp;/^a/n;s/b/m/gp' m
mmmm

[root@localhost ~]# sed -n 's/b/o/gp;/^a/n;s/b/m/gp' m
mmmm

上面两条命令证明了n命令不会从头应用命令,而是直接运用后续的命令。

[root@localhost ~]# cat m
aaaaa
bbbb
oooo

mmmm
[root@localhost ~]# sed  '/.*/{
n
/^ *$/d
}' m
aaaaa
bbbb
oooo
mmmm
[root@localhost ~]# cat m
aaaaa
bbbb

mmmm
[root@localhost ~]# sed  '/.*/{
n
/^ *$/d
}' m
aaaaa
bbbb

mmmm

上面的实践说明了n命令是成对处理行的,所以如果是基数行,一般要用$!n来替换n,关于$!n可以参考后面的。


2):读和写文件

[root@localhost ~]# cat m
aaaaa
bbbb

mmmm
[root@localhost ~]# cat t
Above is a first
[root@localhost ~]# sed -n '/^a/r t' m
Above is a first

和以前的c,a,i命令一样,不管你有没有指定p命令,都会打印非模式空间中的内容。

题外:尾部替换

[root@localhost ~]# sed -n 's/h$/o/gp' m
mmmmho

3):退出命令q

退出命令会立即从sed退出,退出前不做任何事,包括p打印当前模式空间。

head -10 /etc/passwd==sed -n '11q;p' /etc/passwd
 
1):n(next)命令
工作模式:打印当前模式空间内容,并清空后立即读入下一行,且读入下一行后不返回命令头,而是继续应用后面的命令。

[root@localhost ~]# cat m
aaaaa
bbbb
[root@localhost ~]# sed -n '/^a/n;s/b/m/gp' m
mmmm

[root@localhost ~]# sed '/^a/n;s/b/m/g' m
aaaaa
mmmm

如果没有指定-n选项,n操作前先打印当前行。

[root@localhost ~]# sed -n 's/b/m/gp;/^a/n;s/b/m/gp' m
mmmm

[root@localhost ~]# sed -n 's/b/o/gp;/^a/n;s/b/m/gp' m
mmmm

上面两条命令证明了n命令不会从头应用命令,而是直接运用后续的命令。

[root@localhost ~]# cat m
aaaaa
bbbb
oooo

mmmm
[root@localhost ~]# sed  '/.*/{
n
/^ *$/d
}' m
aaaaa
bbbb
oooo
mmmm
[root@localhost ~]# cat m
aaaaa
bbbb

mmmm
[root@localhost ~]# sed  '/.*/{
n
/^ *$/d
}' m
aaaaa
bbbb

mmmm

上面的实践说明了n命令是成对处理行的,所以如果是基数行,一般要用$!n来替换n,关于$!n可以参考后面的。


2):读和写文件

[root@localhost ~]# cat m
aaaaa
bbbb

mmmm
[root@localhost ~]# cat t
Above is a first
[root@localhost ~]# sed -n '/^a/r t' m
Above is a first

和以前的c,a,i命令一样,不管你有没有指定p命令,都会打印非模式空间中的内容。

题外:尾部替换

[root@localhost ~]# sed -n 's/h$/o/gp' m
mmmmho

3):退出命令q

退出命令会立即从sed退出,退出前不做任何事,包括p打印当前模式空间。

head -10 /etc/passwd==sed -n '11q;p' /etc/passwd
阅读(820) | 评论(0) | 转发(0) |
0

上一篇:sed高级命令助记

下一篇:awk1line

给主人留下些什么吧!~~