5:正则表达式的特殊字符与一般在命令行输入命令的通配符并不相同,例如,在通配符中,(*)代表0到无限个字符,但在正则表达式中,(*)则是重复0到多个前面一个字符的意思,使用的意义并不相同,不要混淆
举例来说,不支持正则表达式的ls工具中,若使用“ls -l *”代表任意文件名的文件,而"ls -l a*"代表以a开头的任何文件名的文件。但在正则表达式中,要找到含有以a开头的文件,则必须要这样做(需要搭配正则表达式的工具):ls | grep -n '^a.*'
1. sed 命令简介
Sed(a stream editor)是流线型、非交互式编辑器。它允许你执行与vi编辑器里一样的编辑任务。Sed 程序不是与编辑器交互式工作的,而是让你在命令行里敲入编辑的命令,给文件命名,然后在屏幕上查看命令输出结果。
2. sed 如何工作
sed 编辑器按一次处理一行的方式来处理文件,并把输出送到屏幕上。
3. sed 可以用寻址的方式来决定想要编辑哪一行。
4. sed 命令和选项
选项 功能
a\ 在当前行上添加一个文本行或者多个文本行
c\ 用新闻本改变(取代)当前行里的文本
d 删除行
e 会打印文件的内容,同时在匹配行的前面标志行号
i\ 在当前行之前插入文本
h 把模式空间内容复制到一个固定缓存
H 把模式空间内容添加到一个固定缓存
g 得到固定缓存里所有的并复制到模式缓存,重写其内容
G 得到固定缓存的内容并复制到模式缓存,添加到里面
I 列出不打印的字符
p 打印行
n 读下一输入行,并开始用下一个命令处理换行符,而不是用第一个命令
q 结束或退出sed
r 从一个文件读如行
! 把命令应用到除了选出的行以外的其他所有行
s 把一个字串替换成另一个替换标志
g 在一行上进行全局替换
p 打印行
w 把行写到一个文件中
x 用模式空间的内容交换固定缓存的内容
y 把一个字符转换成另一个(不能和整则表达式元字符一起使用)
5、 sed元字符
基本上,grep和vi使用的元字符都可以用在sed中,&是特例:
& :保存搜索串以便可以记在替换串里
e.g.: s/love/**&**/
&号代表搜索串。串love将被星号包围的自身所替代;即love变成**love**
6 sed实例
1> 打印:p命令
sed '/north/p' datafile
默认输出所有行,找到north的行重复打印
sed �Cn '/north/p' datafile
禁止默认输出,只打印找到north的行
2> 删除:d命令
sed '3d' datafile
删除第三行,其余行输出到屏幕
sed '3,$d' datafile
从第3行到最后一行都删除,将剩余部分输出到屏幕
sed '/north/d' datafile
将含有north的行删除,其余输出到屏幕
3> 替换:s命令
sed 's/west/north/g' datafile
解释:找到datafile中的所有west并替换成north,将替换后的内容输出到屏幕。
sed 's/[0-9][0-9]$/&.5/' datafile
解释:在替代串里的&字符代表在搜索串中真正找到的。
每个以两个数字结尾的行都被它自己取代,且要在后面加上.5
sed -n 's/Hemenway/Jones/gp' datafile
解释:所有的Hemenway所在的位置都用Jones来取代,而且只有改变的行被打印。
-n与p命令选项相结合来禁止默认输出。g代表全局替换
sed -n 's/\(Mar\)got/\1ianne/p' datafile
解释:模式Mar被封装在括弧里且在一个专用寄存器里存为标记1。
在替换串里它将被引用做\1。然后用Marianne替代Margot。
sed 's#3#88#g' datafile
解释:s命令后面的字符是搜索串和替换串之间的分界符。
默认的分界符是一个正斜杠,但也可以改变(只有使用s命令时)。
无论s命令后面跟什么字符,它都是新的串分界符。
当搜索包含一个正斜杠的模式,如路径或生日时,这种技巧可能有用
4> 被选中的行的范围:逗号
sed -n '/west/,/east/p' datafile
打印在west和east之间的模式范围内所有行。如果west出现在east之后,
则打印从west到下一个east或者到文件末尾的行,无论哪种情况先出现都可以。
sed '/west/,/east/s/$/**VACA**/' datafile
解释:对于在模式west到east范围内的行,行末尾将用**VACA**来取代。
5> 多次编辑 -e 选项
sed -e '1,3d' -e 's/Hemenway/Jones/' datafile
-e选项允许多次编辑。不同的编辑顺序可能导致不同的结果。
例如,如果两个命令都执行了替换,第一次替换可能影响第二次替换。
6> 从文件中读取:r命令
sed '/Suan/r newfile' datafile
解释:r命令从newfile中读取内容,将内容输出到Suan的后面。
如果datafile中Suan出现的次数不只一次,则分别放到Suan的后面。
7> 写入文件:w命令
sed -n '/north/w newfile' datafile
解释:w命令把指定的行写入到一个文件。
本例中所有的包含north的行写入到newfile中。
等同于sed -n '/north/p' datafile >newfile
8> 添加:a命令
$ sed '/north/a\
> ---->THE NORTH SALES DISTRICT HAS MOVED<-----' datafile
northwest NW Charles Main 3.0 .98 3 34
---->THE NORTH SALES DISTRICT HAS MOVED<-----
解释:红颜色的内容是要输入的内容。a\命令后面跟要添加的内容。
奇怪的是a\后面必须另起一行,在输入要添加的内容,否则会提示解析错误。
9> 插入:i命令
$ sed '/north/i\
> ---->THE NORTH SALES DISTRICT HAS MOVED<-----' datafile
---->THE NORTH SALES DISTRICT HAS MOVED<-----
northwest NW Charles Main 3.0 .98 3 34
解释:在符合模式的行前面插入内容。其余和a\命令相同。
10>下一个:n命令
$ sed '/eastern/{n;s/AM/Archie/;}' datafile
eastern EA TB Savage 4.4 .84 5 20
northeast NE Archie Main Jr. 5.1 .94 3 13
……
解释:如果在某一行里模式eastern被匹配,n命令使sed区的下一行,
用该行代换模式空间,用Archie替换AM,打印并继续。
11>变换:y 命令
sed '1,3y/abcdefghijklmnopqrst/ABCDEFGHIJKLMNOPQRST/' datafile
解释:将对应字母进行转换。
12>退出:q 命令
sed '5q' datafile
解释:在打印了5行之后,用q命令退出sed程序。
13>保存和取得:h和G命令
$ sed -e '/southeast/h' -e '$G' datafile
解释:当sed 处理文件时,每行都存在模式空间(pattern space)的临时缓存中。除非行被禁止打印或删除,否则行将在处理完后被打印到屏幕,然后请模式空间并把下一输入行保存在那里等待处理。在这个例子中,在找到模式之后,把它放在模式空间里,而且h命令复制它并把它存到另一个叫做保存缓存(holding buffer)中。第二个sed指令里,当读入最后一行($)时,G命令告诉sed从包存缓存中取得该行并放回模式空间缓存,添加到当前存在那里的行中。本例子就是最后一行。
$ sed -e '/WE/{h;d;}' -e '/CT/G' datafile
解释:第一个命令h将找到了WE的行放到保存缓存中,然后删除该行;第二个命令/CT/G就是在找到了CT的行的后面加入保存缓存的内容。
14>G和g的区别
G命令在符合的条件行后面添加保存缓存中的内容;g命令用保存缓存中
15>sed 命令的花括号{}的作用
花括号{}中可以放入多个命令,每个命令后面要用分号;。
16>保存和交换:h 和 x命令。
$ sed -e '/Patricia/h' -e '/Margot/x' datafile
解释:x命令将找到的行用保存缓存中的内容替换。
7. 用sed来编写命令表
sed 命令表(script)是文件里的一个sed命令列表。用-f选项来引用一个命令表文件。编辑sed命令表有特殊要求:命令末尾不能有任何尾随的空白符或者文本。如果命令不是自成一行,就必须用分号结束。
一. sed关于\1,\2,……的解释: sed 's/\(...\)/\1/g' a #其中\1作为寄存器,对应\(*\)的内容,\(*\)里面可以使用正则表达式表示希望截获的字段。比如sed 's/AB\([0-9]\{4\}\)/\1/g' file 将AB后连续出现的4个数字送到寄存器1。sed的寄存器一共可以用9个(1-9)。二. awk substr用法。 substr用途类似于sed的寄存器,(比sed快多了)。 #date 2007年 10月 25日 星期四 15:33:39 CST #date | awk '{a1=substr($0,1,4);a2=substr($0,7,2);print a1"-"a2}' 2007-10 substr(列号,起点,偏移量) 可以做到抽取固定位置某长度字节流给指定变量,最后打印出来就行啦。三. awk NR和FNR意思 对于一个文件NR和FNR都是一样的,对于多个文件,由于NR是累计的,FNR是当前的行,所以文件不同时,FNR永远小于NR!四. awk数组。 案例:给你一个文件,里面很多重复行,现在要求用个脚本去除重复行并打印出来。如何做? 一般结构化思想是读入一行,然后扫描其他行是否匹配,匹配就删掉这行。这么干肯定能完成需求,但是速度嘛... awk也能处理重复行,前提是你机器内存够大,处理文本的2-3倍容量,遇到超标只能把文件split成几个再来了。awk使用数组来去重,思想是把所有 比较的内容放入一个数组中,如果重复那么相对应的组元值就加1,最后统计下来打印组元便得到不重复内容,打印组元值得到重复次数。 awk '{count[$0]++}END{for(number in count)print number","count[number]}' 以上number便是内容,count[number]为重复次数。awk处理重复行,1G的文件只要30秒。不过设备内存要大。awk去重也有坏处,由 于awk数组使用hash算法,最后得到的结果顺序是乱的,如果文件遵循可排序原则到没什么麻烦,去完后sort一次就成了。如果文件本身就没规律乱排 序,想得到原始顺序就很难了。(可以考虑先打印NF值到文件,然后查询文件排序?猜想而已,没写过)以下实例摘自CU SHELL区:cat file1:
0011AAA 200.00 20050321
0012BBB 300.00 20050621
0013DDD 400.00 20050622
0014FFF 500.00 20050401
cat file2:
I0011 11111
I0012 22222
I0014 55555
I0013 66666
规则:比较 file1的1-4字符 和 file2的2-5 字符,如果相同,将file2 的第二列 与 file1 合并 file3
0011AAA 200.00 20050321 11111
0012BBB 300.00 20050621 22222
0013DDD 400.00 20050622 66666
0014FFF 500.00 20050401 55555code:awk 'NR==FNR{a[substr($1,2,5)]=$2}NR>FNR&&a[b=substr($1,1,4)]{print $0, a[b]}' file2 file1 >file33、如果文件a中包含文件b,则将文件b的记录打印出来
http://bbs.chinaunix.net/forum/viewtopic.php?t=520411
文件a:
10/05766798607,11/20050325191329,29/0.1,14/05766798607
10/05767158557,11/20050325191329,29/0.08,14/05767158557
文件b:
05766798607
05766798608
05766798609
通过文件a和文件b对比,导出这样的文件出来.
10/05766798607,11/20050325191329,29/0.1,14/05766798607code:awk -F'[/,]' 'ARGIND==1{a[$0]}ARGIND>1{($2 in a);print $0}' b a
awk -F'[/,]' 'NR==FNR{a[$0]}NR>FNR{($2 in a);print $0}' b afile1文件内容
1 0.5 100
10 15 36.5
file2文件
50 10 9
3.2 1 5
将两个文件合成一个文件如:
51 10.5 109
13.2 16 41.5
就是对应的字段进行相加以后的数字。
awk '{for (i=1;i<=NF;i++) a=$i
getline <"file2"
for (i=1;i<NF;i++) printf $i+a" ";
printf $NF+a[NF] "\n"}' file1
code:awk '{for (i=1;i<=NF;i++) a[i]=$i;getline <"file2";for (i=1;i<NF;i++) printf $i+a[i]" ";printf $NF+a[NF] "\n"}' file1 文件a
1000 北京市 地级 北京市 北京市
1100 天津市 地级 天津市 天津市
1210 石家庄市 地级 石家庄市 河北省
1210 晋州市 县级 石家庄市 河北省
1243 滦县 县级 唐山市 河北省
1244 滦南县 县级 唐山市 河北省
b文件:
110000,北京市
120000,天津市
130000,河北省
130131,平山县
130132,元氏县
这样的字段
a中第二列在b中可能有可能没有,需要把有的匹配起来生成新的一列:要包含a和b的第一列。没有匹配的按照b原来的格式进行输出。code:awk 'BEGIN{FS="[ |,]";OFS=","}NR<=FNR{a[$2]=$1}NR>FNR{print $1,$2,a[$2]}' a bfile1的第一列与file2的第3列相同,
file1的第二列与file2的第4列的3-5位相同,
file1的第三列与file2的最后一列相同,
# cat file1
AAA 001 1000.00
BBB 001 2000.00
DDD 002 4000.00
EEE 002 5000.00
FFF 003 6000.00
# cat file2
01 1111 AAA WW001 $$$$ 1000.00
02 2222 BBB GG001 %%%% 2000.00
03 3333 CCC JJ001 **** 3000.00
04 4444 DDD FF002 &&&& 4000.00
05 5555 EEE RR002 @@@@ 5000.00
06 666 FFF UU003 JJJJ 6000.00
07 777 III II005 PPPP 7000.00
08 8888 TTT TT008 TTTT 8000.00code:awk 'NR<=FNR{a[$1]=$1"x"$2"x"$3}
> NR>FNR{b=substr($4,3);c=$3"x"b"x"$6;if(c==a[$3]) print}' file1 file2
二.关于sed中N和n的例子
主要就是N是追加下面的行到模式空间,n是替换模式空间中的内容
参看cu例子:
http://bbs2.chinaunix.net/viewthread.php?tid=1009680&extra=&page=1
三.打印一个文件的奇数行和偶数行
方法一:
1,awk 'NR%2==1' file
2,awk 'NR%2==0' file
方法二:
sed -n 'p;n' urf
sed -n 'n;p' urf
方法三:
sed -n '1~2p'
sed -n '2~2p'
方法四:
awk '{print $0 > NR%2}' file