shell正则表达式及grepfindawksed

一,grep

1,基础参数
grep-[acinv]'搜索内容串'filename
-a以文本文件方式搜索
-c计算找到的符合行的次数
-i忽略大小写
-n顺便输出行号
-v反向选择,即找没有搜索字符串的行

[root@test3 ~]# cat Travel.doc
Travel is a good way to refresh and broaden our horizon.
During your travel, you can turn off your cellphone and keep far from the Internet.
You can forget your work, your study or your family, and just enjoy the leisure time. From the moment when you start your journey, all the trifles should be locked at your house.
During the travel, you can kill your time slowly to have a good rest, and you can contact with different people.
They may be a window for you to know a different world.
Meet various people, experience things, which make your world bigger.
You just clean up your entire mind and you can get the true meaning of travel.
找出有The的行,并打印行号
[root@test3 ~]# grep -n "The" Travel.doc
5:They may be a window for you to know a different world.
搜索没有The的行
[root@test3 ~]# grep -vn "The" Travel.doc
1:Travel is a good way to refresh and broaden our horizon.
2:During your travel, you can turn off your cellphone and keep far from the Internet.
3:You can forget your work, your study or your family, and just enjoy the leisure time. From the moment when you start your journey, all the trifles should be locked at your house.
4:During the travel, you can kill your time slowly to have a good rest, and you can contact with different people.
6:Meet various people, experience things, which make your world bigger.
7:You just clean up your entire mind and you can get the true meaning of travel.
计算含有travel单词的行数,不区分大小写
[root@test3 ~]# grep  -nic  "travel" Travel.doc
4

2利用[]搜索集合字符
[]表示其中的某一个字符,例如[ade]表示a或d或e

找出ting hing ning
[root@test3 ~]# grep -ni "[thn]ing" Travel.doc
6:Meet various people, experience things, which make your world bigger.
7:You just clean up your entire mind and you can get the true meaning of travel.

用^符号做[]内的前缀,表示除[]内的字符之外的字符。
比如搜索oo前没有g的字符串所在的行.使用'[^g]oo'作搜索字符串

[root@test3 ~]# grep -ni "[^g]oo" Travel.doc
8:foo

[]内可以用范围表示,比如[a-z]表示小写字母,[0-9]表示0~9的数字,[A-Z]则是大写字母们。[a-zA-Z0-9]表示所有数字与英文字符。当然也可以配合^来排除字符。

[root@test3 ~]# grep -ni "[1-9]" Travel.doc
9:2020 12 31


3,行首与行尾字符^$

^表示行的开头,$表示行的结尾(不是字符,是位置)那么‘^$'就表示空行,因为只有
行首和行尾。
这里^与[]里面使用的^意义不同。它表示^后面的串是在行的开头。
比如搜索Travel在开头的行

[root@test3 ~]# grep -ni "^Travel" Travel.doc
1:Travel is a good way to refresh and broaden our horizon.


4,搜索以小写字母开头的行

[root@test3 ~]# grep -n "^[a-z]" Travel.doc
8:foot


5,搜索开头不是英文字母的行


[root@test3 ~]# grep -n "^[^a-zA-Z]" Travel.doc
9:2020 12 31


6,$表示它前面的串是在行的结尾,

比如'\.'表示.在一行的结尾
搜索末尾是.的行

[root@test3 ~]# grep -n "\.$" Travel.doc
1:Travel is a good way to refresh and broaden our horizon.
2:During your travel, you can turn off your cellphone and keep far from the Internet.
3:You can forget your work, your study or your family, and just enjoy the leisure time.
4:From the moment when you start your journey, all the trifles should be locked at your house.
5:During the travel, you can kill your time slowly to have a good rest, and you can contact with different people.
6:They may be a window for you to know a different world.
7:Meet various people, experience things, which make your world bigger.
8:You just clean up your entire mind and you can get the true meaning of travel.

7,任意一个字符.与重复字符*

在bash中*代表通配符,用来代表任意个字符,但是在正则表达式中,他含义不同,*表示有0个或多个某个字符。
例如oo*,表示第一个o一定存在,第二个o可以有一个或多个,也可以没有,因此代表至少一个o.
点.代表一个任意字符,必须存在。

g??d可以用'g..d'表示。good,gxxd,gabd.....都符合。

a,搜索两个o以上的字符串

[root@test3 ~]# cat a.sh
good
foot
vnhsdooos
[root@test3 ~]# grep -n "ooo*" a.sh
1:good
2:foot
3:vnhsdooos

b,搜索g开头和结尾的字符串在的行.*表示0个或多个任意字符

[root@test3 ~]# cat b.sh
"Open Source" is a good mechanism to develop programs.
The gd software is a library for drafting programs.
google is the best tools for search keyword.
goooooogle yes!
go! go! Let's go.
[root@test3 ~]# grep -n 'g.*g' b.sh
1:"Open Source" is a good mechanism to develop programs.
2:The gd software is a library for drafting programs.
3:google is the best tools for search keyword.
4:goooooogle yes!
5:go! go! Let's go.


8,限定连续重复字符的范围{}
.*只能限制0个或多个,如果要确切的限制字符重复数量,就用{范围}。范围是数字用,隔开2,5表示2~5个,
2表示2个,2,表示2到更多个
注意,由于{}在SHELL中有特殊意义,因此作为正则表达式用的时候要用\转义一下。

搜索包含两个o的字符串的行。
woody@xiaoc:~/tmp$grep-n'o\{2\}'regular_express.txt
1:"OpenSource"isagoodmechanismtodevelopprograms.
2:appleismyfavoritefood.
3:Footballgameisnotusefeetonly.
9:Oh!thesouptastegood!
18:googleisthebesttoolsforsearchkeyword.
19:goooooogleyes!

搜索g后面跟2~5个o,后面再跟一个g的字符串的行。
woody@xiaoc:~/tmp$grep-n'go\{2,5\}g'regular_express.txt
18:googleisthebesttoolsforsearchkeyword.

搜索包含g后面跟2个以上o,后面再跟g的行。。
woody@xiaoc:~/tmp$grep-n'go\{2,\}g'regular_express.txt
18:googleisthebesttoolsforsearchkeyword.
19:goooooogleyes!

注意,相让[]中的^-不表现特殊意义,可以放在[]里面内容的后面。
'[^a-z\.!^-]'表示没有小写字母,没有.没有!,没有空格,没有-的串,注意[]里面有个小空格。

这里列出几个扩展特殊符号:
+,于.*作用类似,表示一个或多个重复字符。
?,于.*作用类似,表示0个或一个字符。
|,表示或关系,比如'gd|good|dog'表示有gd,good或dog的串
(),将部分内容合成一个单元组。比如要搜索glad或good可以这样'g(la|oo)d'
()的好处是可以对小组使用+?*等。
比如要搜索A和C开头结尾,中间有至少一个(xyz)的串,可以这样:'A(xyz)+C'


二,awk

1、awk'/101/'file显示文件file中包含101的匹配行。

[root@test3 ~]# awk '/192.168.46.1/' /usr/local/apache2/logs/access_log
192.168.46.1 - - [11/Sep/2013:22:59:16 -0700] "GET / HTTP/1.1" 401 381
192.168.46.1 - chen [11/Sep/2013:22:59:22 -0700] "GET / HTTP/1.1" 200 55085
192.168.46.1 - chen [11/Sep/2013:22:59:38 -0700] "GET / HTTP/1.1" 200 55085

awk'/101/,/105/'file
awk'$1==5'file

[root@test3 ~]# awk '$1=="192.168.46.1" ' /usr/local/apache2/logs/access_log
192.168.46.1 - - [11/Sep/2013:22:59:16 -0700] "GET / HTTP/1.1" 401 381
192.168.46.1 - chen [11/Sep/2013:22:59:22 -0700] "GET / HTTP/1.1" 200 55085
192.168.46.1 - chen [11/Sep/2013:22:59:38 -0700] "GET / HTTP/1.1" 200 55085

awk'$1=="CT"'file注意必须带双引号
awk'$1*$2>100'file
awk'$2>5&&$2<=15'file

220149969.jpg

2、awk'{printNR,NF,$1,$NF,}'file

显示文件file的当前记录号、域数和每一行的第一个和最后一个域。
awk'/101/{print$1,$2+10}'file显示文件file的匹配行的第一、二个域加10。
awk'/101/{print$1$2}'file显示文件file的匹配行的第一、二个域,但显示时域中间没有分隔符。

变量名                含义
ARGC                命令行变元个数
ARGV                命令行变元数组
FILENAME        当前输入文件名
FNR                当前文件中的记录号
FS                输入域分隔符,默认为一个空格
RS                输入记录分隔符
NF                当前记录里域个数
NR                到目前为止记录数
OFS                输出域分隔符
ORS                输出记录分隔符


3、df|awk'$4>1000000'通过管道符获得输入,如:显示第4个域满足条件的行。

4、按照新的分隔符“|”进行操作。

awk-F"|"'{print$1}'file

awk'BEGIN{FS="[:\t|]"}
{print$1,$2,$3}'file通过设置输入分隔符(FS="[:\t|]")修改输入分隔符。
Sep="|"
awk-F$Sep'{print$1}'file按照环境变量Sep的值做为分隔符。
awk-F'[:\t|]''{print$1}'file按照正则表达式的值做为分隔符,这里代表空格、:、TAB、|同时做为分隔符。
awk-F'[][]''{print$1}'file按照正则表达式的值做为分隔符,这里代表[、]

5、awk-fawkfilefile通过文件awkfile的内容依次进行控制。
catawkfile
/101/{print"\047Hello!\047"}--遇到匹配行以后打印'Hello!'.\047代表单引号。
{print$1,$2}--因为没有模式控制,打印每一行的前两个域。


6、awk'$1~/101/{print$1}'file显示文件中第一个域匹配101的行(记录)。

[root@test3 ~]# awk '$1 ~ /127.0.0.1/{print $1}'  /usr/local/apache2/logs/access_log
127.0.0.1
127.0.0.1
127.0.0.1
127.0.0.1
127.0.0.1
127.0.0.1
127.0.0.1

7、awk'BEGIN{OFS="%"}
{print$1,$2}'file通过设置输出分隔符(OFS="%")修改输出格式。


8、awk'BEGIN{max=100;print"max="max}BEGIN表示在处理任意行之前进行的操作。
{max=($1>max?$1:max);print$1,"Nowmaxis"max}'file取得文件第一个域的最大值。
(表达式1?表达式2:表达式3相当于:
if(表达式1)
表达式2
else
表达式3
awk'{print($1>4?"high"$1:"low"$1)}'file


9、awk'$1*$2>100{print$1}'file显示文件中第一个域匹配101的行(记录)。

10、awk'{$1=='Chi'{$3='China';print}'file找到匹配行后先将第3个域替换后再显示该行(记录)。
awk'{$7%=3;print$7}'file将第7域被3除,并将余数赋给第7域再打印。


11、awk'/tom/{wage=$2+$3;printfwage}'file找到匹配行后为变量wage赋值并打印该变量。


12、awk'/tom/{count++;}
END{print"tomwasfound"count"times"}'fileEND表示在所有输入行处理完后进行处理。


13、awk'gsub(/\$/,"");gsub(/,/,"");cost+=$4;
END{print"Thetotalis$"cost>"filename"}'filegsub函数用空串替换$和,再将结果输出到filename中。
123$1,200.00
123$2,300.00
123$4,000.00

awk'{gsub(/\$/,"");gsub(/,/,"");
if($4>1000&&$4<2000)c1+=$4;
elseif($4>2000&&$4<3000)c2+=$4;
elseif($4>3000&&$4<4000)c3+=$4;
elsec4+=$4;}
END{printf"c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"'file
通过if和elseif完成条件语句

awk'{gsub(/\$/,"");gsub(/,/,"");
if($4>3000&&$4<4000)exit;
elsec4+=$4;}
END{printf"c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"'file
通过exit在某条件时退出,但是仍执行END操作。
awk'{gsub(/\$/,"");gsub(/,/,"");
if($4>3000)next;
elsec4+=$4;}
END{printf"c4=[%d]\n",c4}"'file
通过next在某条件时跳过该行,对下一行执行操作。


14、awk'{printFILENAME,$0}'file1file2file3>fileall把file1、file2、file3的文件内容全部写到fileall中,格式为
打印文件并前置文件名。


15、awk'$1!=previous{close(previous);previous=$1}
{printsubstr($0,index($0,"")+1)>$1}'fileall把合并后的文件重新分拆为3个文件。并与原文件一致。


16、awk'BEGIN{"date"|getlined;printd}'通过管道把date的执行结果送给getline,并赋给变量d,然后打印。


17、awk'BEGIN{system("echo\"Inputyourname:\\c\"");getlined;print"\nYournameis",d,"\b!\n"}'
通过getline命令交互输入name,并显示出来。
awk'BEGIN{FS=":";while(getline<"/etc/passwd">0){if($1~"050[0-9]_")print$1}}'
打印/etc/passwd文件中用户名包含050x_的用户名。

18、awk'{i=1;while(i<NF){printNF,$i;i++}}'file通过while语句实现循环。
awk'{for(i=1;i<NF;i++){printNF,$i}}'file通过for语句实现循环。
typefile|awk-F"/"'
{for(i=1;i<NF;i++)
{if(i==NF-1){printf"%s",$i}
else{printf"%s/",$i}}}'显示一个文件的全路径。
用for和if显示日期
awk'BEGIN{
for(j=1;j<=12;j++)
{flag=0;
printf"\n%d月份\n",j;
for(i=1;i<=31;i++)
{
if(j==2&&i>28)flag=1;
if((j==4||j==6||j==9||j==11)&&i>30)flag=1;
if(flag==0){printf"%02d%02d",j,i}
}
}
}'
19、在awk中调用系统变量必须用单引号,如果是双引号,则表示字符串
Flag=abcd
awk'{print'$Flag'}'结果为abcd
awk'{print"$Flag"}'结果为$Flag


三,find

查当前目录下的所有普通文件
#find.-typef-execls-l{}\;
-rw-r–r–1rootroot349282003-02-25./conf/httpd.conf
-rw-r–r–1rootroot129592003-02-25./conf/magic
-rw-r–r–1rootroot1802003-02-25./conf.d/README
查当前目录下的所有普通文件,并在-exec选项中使用ls-l命令将它们列出

=================================================
在/logs目录中查找更改时间在5日以前的文件并删除它们:
$findlogs-typef-mtime+5-exec-okrm{}\;

=================================================
查询当天修改过的文件
[root@bookclass]#find./-mtime-1-typef-execls-l{}\;

=================================================
查询文件并询问是否要显示
[root@bookclass]#find./-mtime-1-typef-okls-l{}\;
<ls…./classDB.inc.php>?y
-rw-r–r–1cnscncnscn137091月1212:22./classDB.inc.php
[root@bookclass]#find./-mtime-1-typef-okls-l{}\;
<ls…./classDB.inc.php>?n
[root@bookclass]#

=================================================
查询并交给awk去处理
[root@bookclass]#who|awk’{print$1"\t"$2}’
cnscnpts/0

=================================================
awk—grep—sed

[root@bookclass]#df-k|awk‘{print$1}’|grep-v’none’|seds"/\/dev\///g"
文件系统
sda2
sda1
[root@bookclass]#df-k|awk‘{print$1}’|grep-v’none’
文件系统
/dev/sda2
/dev/sda1

1)在/tmp中查找所有的*.h,并在这些文件中查找“SYSCALL_VECTOR",最后打印出所有包含"SYSCALL_VECTOR"的文件名

A)find/tmp-name"*.h"|xargs-n50grepSYSCALL_VECTOR
B)grepSYSCALL_VECTOR/tmp/*.h|cut-d’:'-f1|uniq>filename
C)find/tmp-name"*.h"-execgrep"SYSCALL_VECTOR"{}\;-print

2)find/-namefilename-execrm-rf{}\;
find/-namefilename-okrm-rf{}\;

3)比如要查找磁盘中大于3M的文件:
find.-size+3000k-execls-ld{};

4)将find出来的东西拷到另一个地方
find*.c-execcp‘{}’/tmp‘;’

如果有特殊文件,可以用cpio,也可以用这样的语法:
finddir-namefilename-print|cpio-pdvnewdir

6)查找2004-11-3016:36:37时更改过的文件
#A=`find./-name"*php"`|ls-l–full-time$A2>/dev/null|grep"2004-11-3016:36:37"


四,sed

sed[options][functions]选项[options]:

-n:使用安静(silent)模式,不在屏幕上显示出来

-e:允许多个sed处理语句,直接大指令列模式上进行sed动作

-f:你可以将sed的动作写在一个档案内,-ffilename则可以执行里面的sed动作

-r:sed的动作支持的是延伸型正则表达式的语法-i:直接修改读取的档案内容,而不是由屏幕输出

动作说明:[n1[,n2]]fuctionn1,n2:代表选择进行动作的行数,如10,20[动作行为]行为[functions]:

a:新增a的后面可以接字符串,字符串会在目前行的下一行显示

d:删除,因为是删除,所以d后面通常不接任何数据^O^

c:取代c的后面可以接字符串,这些字符串可以取代n1,n2之间的行

i:插入i的后面可以接字符串,而这些字符串会目前行的上一行显示

p:打印,让特定的数据显示,通常p会与参数sed-n一起使用

s:取代,可以直接进行取代工作,如1,20s/old/new/g

范例一:使用行为a(新增)

[root@www~]nl/etc/passwd|sed'2a在第2行后面添加数据'1root:x:0:0:root:/root:/bin/bash2daemon:x:1:1:daemon:/usr/sbin:/bin/sh在第2行后面添加数据

范例二:使用行为d(删除)[root@www~]nl/etc/passwd|sed'2,5d'

范例三:使用行为c(取代行)[root@www~]nl/etc/passwd|sed'2,5c2-5行之间的数据被我取代了'1root:x:0:0:root:/root:/bin/bash2-5行之间的数据被我取代了6games:x:5:60:games:/usr/games:/bin/sh

范例四:仅列出/etc/passwd文件内的第5-7[root@www~]nl/etc/passwd|sed-n'5,7p'5sync:x:4:65534:sync:/bin:/bin/sync6games:x:5:60:games:/usr/games:/bin/sh7man:x:6:12:man:/var/cache/man:/bin/sh

范例五:使用sedifconfig只输出ip地址5.1.首先使用ifconfigeth0[接口名]查看详细信息[root@www~]ifconfig

eth0eth0Linkencap:以太网硬件地址00:23:ae:68:84:e4inet地址:192.168.10.123广播:192.168.10.255掩码:255.255.255.0inet6地址:fe80::223:aeff:fe68:84e4/64Scope:LinkUPBROADCASTRUNNINGMULTICASTMTU:1500跃点数:1接收数据包:26597错误:0丢弃:0过载:0帧数:0发送数据包:17358错误:0丢弃:0过载:0载波:0碰撞:0发送队列长度:1000接收字节:25801312(25.8MB)发送字节:2114879(2.1MB)中断:165.2.使用grep进行过滤显示[root@www~]ifconfigeth0|grep'inet'inet地址:192.168.10.123广播:192.168.10.255掩码:255.255.255.05.3.使用sed正则表达式去前面部分(^.*地址:)

[root@www~]ifconfigeth0|grep'inet'|sed's/^.*地址://g'192.168.10.123广播:192.168.10.255掩码:255.255.255.05.4.使用sed正则表达式去后面部分(广播.*$)

[root@www~]ifconfigeth0|grep'inet'|sed's/^.*地址://g'|sed's/广播.*$//g'192.168.10.1235.5.使用-e选项[root@www~]ifconfigeth0|grep'inet'|sed-e's/^.*地址://g'-e's/广播.*$//g'192.168.10.1235.6.使用-f选项(把参数写到sedfile文件中)

[root@www~]ifconfigeth0|grep'inet'|sed-fsedfile192.168.10.123

范例六:/etc/manpath.config只要MAN存在的行,但是含有#在内的批注行和空白行不要

[root@www~]cat/etc/manpath.config|grepMAN|sed's/^#.*//g'|sed'/^$/d'

MANDATORY_MANPATH/usr/manMANDATORY_MANPATH/usr/share/manMANDATORY_MANPATH/usr/local/share/manMANPATH_MAP/bin/usr/share/manMANPATH_MAP/usr/bin/usr/share/manMANPATH_MAP/sbin/usr/share/manMANPATH_MAP/usr/sbin/usr/share/manMANPATH_MAP/usr/local/bin/usr/local/manMANPATH_MAP/usr/local/bin/usr/local/share/manMANPATH_MAP/usr/local/sbin/usr/local/manMANPATH_MAP/usr/local/sbin/usr/local/share/manMANPATH_MAP/usr/X11R6/bin/usr/X11R6/manMANPATH_MAP/usr/bin/X11/usr/X11R6/manMANPATH_MAP/usr/games/usr/share/manMANPATH_MAP/opt/bin/opt/manMANPATH_MAP/opt/sbin/opt/manMANDB_MAP/usr/man/var/cache/man/fsstndMANDB_MAP/usr/share/man/var/cache/manMANDB_MAP/usr/local/man/var/cache/man/oldlocalMANDB_MAP/usr/local/share/man/var/cache/man/localMANDB_MAP/usr/X11R6/man/var/cache/man/X11R6MANDB_MAP/opt/man/var/cache/man/opt

范例七:利用sedsedtext内的每一结尾为.的换成!sedtext的文件内容如下:"OpenSource"isagoodmechanismtodevelopprograms.appleismyfavoritefood.Footballgameisnotusefeetonly.thisdressdoesn'tfitme.However,thisdressisabout$3183dollars.GNUisfreeairnotfreebeer.Herhairisverybeauty.Ican'tfinishthetest.Oh!Thesouptastegood.motorcycleischeapthancar.Thiswindowisclear.thesymbol'*'isrepresentedasstart.Oh!Mygod!Thegdsoftwareisalibraryfordraftingprograms.Youarethebestismeanyouaretheno.1.Theworld<Happy>isthesamewith"glad".Ilikedog.googleisthebesttoolsforsearchkeyword.goooooogleyes!go!go!Let'sgo.

[root@www~]catsedtext|sed's/\.$/\!/g'"OpenSource"isagoodmechanismtodevelopprograms!appleismyfavoritefood!Footballgameisnotusefeetonly!thisdressdoesn'tfitme!However,thisdressisabout$3183dollars!GNUisfreeairnotfreebeer!Herhairisverybeauty!Ican'tfinishthetest!Oh!Thesouptastegood!motorcycleischeapthancar!Thiswindowisclear!thesymbol'*'isrepresentedasstart!Oh!Mygod!Thegdsoftwareisalibraryfordraftingprograms!Youarethebestismeanyouaretheno.1!Theworld<Happy>isthesamewith"glad"!Ilikedog!googleisthebesttoolsforsearchkeyword!goooooogleyes!go!go!Let'sgo!


五,sort

sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式:
sort [-bcfMnrtk][源文件][-o 输出文件]
补充说明:sort可针对文本文件的内容,以行为单位来排序。

参  数:
-b 忽略每行前面开始出的空格字符。
-c 检查文件是否已经按照顺序排序。
-f 排序时,忽略大小写字母。
-M 将前面3个字母依照月份的缩写进行排序。
-n 依照数值的大小排序。
-o<输出文件> 将排序后的结果存入指定的文件。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
-k 选择以哪个区间进行排序。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

下面通过几个例子来讲述Sort的使用。

(1)sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

[rocrocket@rocrocket programming]$ cat seq.txt
banana
apple
pear
orange
[rocrocket@rocrocket programming]$ sort seq.txt
apple
banana
orange
pear

用户可以保存排序后的文件内容,或把排序后的文件内容输出至打印机。下例中用户把排序后的文件内容保存到名为result的文件中。
$ Sort seq.txt > result

(2)sort的-u选项

它的作用很简单,就是在输出行中去除重复行。

[rocrocket@rocrocket programming]$ cat seq.txt
banana
apple
pear
orange
pear
[rocrocket@rocrocket programming]$ sort seq.txt
apple
banana
orange
pear
pear
[rocrocket@rocrocket programming]$ sort -u seq.txt
apple
banana
orange
pear

pear由于重复被-u选项无情的删除了。

(3)sort的-r选项

sort默认的排序方式是升序,如果想改成降序,就加个-r就搞定了。

[rocrocket@rocrocket programming]$ cat number.txt
1
3
5
2
4
[rocrocket@rocrocket programming]$ sort number.txt
1
2
3
4
5
[rocrocket@rocrocket programming]$ sort -r number.txt
5
4
3
2
1
(5)sort的-o选项

由于sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如sort filename > newfile。

但是,如果你想把排序结果输出到原文件中,用重定向可就不行了。

[rocrocket@rocrocket programming]$ sort -r number.txt > number.txt
[rocrocket@rocrocket programming]$ cat number.txt
[rocrocket@rocrocket programming]$
看,竟然将number清空了。

就在这个时候,-o选项出现了,它成功的解决了这个问题,让你放心的将结果写入原文件。这或许也是-o比重定向的唯一优势所在。

[rocrocket@rocrocket programming]$ cat number.txt
1
3
5
2
4
[rocrocket@rocrocket programming]$ sort -r number.txt -o number.txt
[rocrocket@rocrocket programming]$ cat number.txt
5
4
3
2
1

(6) sort的-n选项

你有没有遇到过10比2小的情况。我反正遇到过。出现这种情况是由于排序程序将这些数字按字符来排序了,排序程序会先比较1和2,显然1小,所以就将10放在2前面喽。这也是sort的一贯作风。

我们如果想改变这种现状,就要使用-n选项,来告诉sort,“要以数值来排序”!

[rocrocket@rocrocket programming]$ cat number.txt
1
10
19
11
2
5
[rocrocket@rocrocket programming]$ sort number.txt
1
10
11
19
2
5
[rocrocket@rocrocket programming]$ sort -n number.txt
1
2
5
10
11
19

(7) sort的-t选项和-k选项

如果有一个文件的内容是这样:

[rocrocket@rocrocket programming]$ cat facebook.txt
banana:30:5.5
apple:10:2.5
pear:90:2.3
orange:20:3.4

这个文件有三列,列与列之间用冒号隔开了,第一列表示水果类型,第二列表示水果数量,第三列表示水果价格。那么我想以水果数量来排序,也就是以第二列来排序,如何利用sort实现?幸好,sort提供了-t选项,后面可以设定间隔符。指定了间隔符之后,就可以用-k来指定列数了。

[rocrocket@rocrocket programming]$ sort -n -k 2 -t ‘:’ facebook.txt
apple:10:2.5
orange:20:3.4
banana:30:5.5
pear:90:2.3


六,uniq

– c 显示输出中,在每行行首加上本行在文件中出现的次数。它可取代- u和- d选项。

– d 只显示重复行。

– u 只显示文件中不重复的各行。

– n 前n个字段与每个字段前的空白一起被忽略。一个字段是一个非空格、非制表符的字符串,彼此由制表符和空格隔开(字段从0开始编号)。

+n 前n个字符被忽略,之前的字符被跳过(字符从0开始编号)。

– f n 与- n相同,这里n是字段数。

– s n 与+n相同,这里n是字符数。

接下来通过实践实例说明:

===========================================

[root@stu100 ~]# cat test
boy took bat home
boy took bat home
girl took bat home
boy took bat home
boy took bat home
dog brought hat home
dog brought hat home
dog brought hat home

看test文件的内容

============================================

[root@stu100 ~]# uniq test
boy took bat home
girl took bat home
boy took bat home
dog brought hat home

uniq命令不加任何参数,仅显示连续重复的行一次

============================================

[root@stu100 ~]# uniq -c test
2 boy took bat home
1 girl took bat home
2 boy took bat home
3 dog brought hat home
1

-c 参数显示文件中每行连续出现的次数。

============================================

[root@stu100 ~]# cat test |sort | uniq -c
1
4 boy took bat home
3 dog brought hat home
1 girl took bat home

排序后再显示

============================================

[root@stu100 ~]# uniq -d test
boy took bat home
boy took bat home
dog brought hat home

-d选项仅显示文件中连续重复出现的行。

============================================

[root@stu100 ~]# uniq -u test
girl took bat home

-u选项显示文件中没有连续出现的行。

============================================

[root@stu100 ~]# uniq -f 2 -s 2 test
boy took bat home

忽略每行的前2个字段,忽略第二 个空白字符和第三个字段的首字符,结果at home

============================================

[root@stu100 ~]# uniq -f 1 test
boy took bat home
dog brought hat home

忽 略每行的第一个字段,这样boy ,girl开头的行看起来是连续重复的行。

============================================

[root@stu100 ~]# uniq -D test
boy took bat home
boy took bat home
boy took bat home
boy took bat home
dog brought hat home
dog brought hat home
dog brought hat home

显示所有重复的行,每个重复的行都显示


七,cut

一、定义

正如其名,cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut是以每一行为一个处理对象的,这种机制和sed是一样的。

2、剪切依据

cut命令主要是接受三个定位方法:

第一,字节(bytes),用选项-b

第二,字符(characters),用选项-c

第三,域(fields),用选项-f

例:

一,按字节cut:

注意:一个空格算一个字节,一个汉字算三个字节

[root@localhost ~]# date

2011年08月11日 星期四20:44:52 EDT

[root@localhost ~]# date |cut -b 1-4 取前四个字节

2011

[root@localhost ~]# date |cut -b 1-6

2011

[root@localhost ~]# date |cut -b 1-7 一个汉字算三个字节

2011年

[root@localhost ~]# date |cut -b 1-10

2011年08

多个定位之间用逗号隔开:

[root@localhost ~]# date |cut -b 1-7,10

2011年8

[root@localhost ~]# date |cut -b 10,1-7 cut会先把-b后面所有的定位进行从小到大排序,然后再提取

2011年8

负号的使用:

[root@localhost ~]# date |cut -b -4

2011

[root@localhost ~]# date |cut -b 4-

1年08月11日 星期四21:05:30 EDT

[root@localhost ~]# date |cut -b -4,4-

2011年08月11日 星期四21:06:53 EDT

-4表示从第一个字节到第四个字节,而4-表示从第四个字节到行尾。这两种情况下,都包括了第4个字节“1”。如果我执行date |cut -b -4,4-,会输出整行,不会出现连续两个重叠的1


二,按字符cut:

按字符cut相对比较简单,中文字符和空格都算一个字符。

[root@localhost ~]# date |cut -c 1-5

2011年

[root@localhost ~]# date |cut -c 5,9,13

年月日


三、按域cut

以/etc/passwd文件为例:

[root@localhost ~]# head -n5 /etc/passwd |cut -d : -f 1,3-5

root:0:0:root

bin:1:1:bin

daemon:2:2:daemon

adm:3:4:adm

lp:4:7:lp

-d指定域分隔符,-f 指定要剪出哪几个域,这个与awk的输出特定字段功能一样。


-d选项的默认间隔符就是制表符,所以当你就是要使用制表符的时候,完全就可以省略-d选项,而直接用-f来取域就可以了

如何分的清空格和制表符?

[root@localhost ~]# cat test 这个文件各单词间存在单个空格、制表符和多个空格

data11【单个空格 】data12 【制表符】data13

data21【多个空格】data22【单个空格】data23

data31 【单个空格 】data32 【 多个空格data33

[root@localhost ~]# sed -n l test 用sed命令可以让制表符原形毕露~

data11 data12\tdata13$

data21 data22 data23$

data31 data32 data33$

[root@localhost ~]# cat test |cut -f 2

data13

data21 data22 data23

data31 data32 data33

[root@localhost ~]# cat test |cut -d " " -f 2 cut的间隔符只允许是一个字符

cut: the delimiter must be a single character

请尝试执行“cut --help”来获取更多信息。

[root@localhost ~]# cat test |cut -d " " -f 2

data12 data13 中间那个空白字符是制表符

第一个空格后面还是空格,所以输出空格

data32 单个空格后面就是data32