一.grep命令与egrep命令(grep命令和egrep命令(相当于grep -E)都是一行一行的匹配)
1.grep命令的使用
<1>grep命令的说明
grep命令提供了在文本中检索特定字符串的方法,它的强大就在于支持正则表达式。
grep命令常常与管道连用,用在文本流中过滤出符合条件的文本行。
grep命令可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。
<2>grep命令格式说明
格式1:grep [参数] 要匹配的字符串 文件名
格式2:命令得到的文本 | grep [参数] 要匹配的字符串
<3>grep命令参数说明
-i参数实践
-v参数实践
-c参数实践
-n参数实践
-q参数实践
-o参数实践
-m参数实践L
2.egrep命令(相当于grep -E)的使用
同grep命令的使用,egrep是grep的扩展。
grep能执行的命令,egrep一定能执行。
但是,有时候,egrep能执行的命令,grep是不能执行的。
我们一般使用egrep。
二.正则表达式(这里的实践以egrep和正则表达式的结合为例。别的命令与正则表达式的结合的使用类比即可。)
/TsingYoung/p/8249782.html
1.正则表达式的说明
正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。
正则表达式是由普通字符(例如字符 a 到 z)以及元字符组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配
支持正则表达式的工具有:
用于匹配文本行的grep工具族(grep和egrep);用于改变输入流的sed流编辑器;用于处理字符串的语言,如awk,python,perl,Tel等语言;文本查看程序,或分页程序,more,page,less等文本编辑器,如ed,vi,emacs,vim等
2.普通字符
由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。
<1>非打印字符
3.元字符
<1>元字符介绍
元字符一般分为特殊字符,数量限定符和位置限定符。
<2>特殊字符
下面介绍常见的特殊字符。
<3>数量限定符
数量限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{,m}或{n,m}共7种。
正则表达式的数量限定符有:
<4>位置限定符
4.实践环境准备
cat -A 在每一行最后加上一个$符号。
cat -b表示在每一个非空行前面加上行号。
5.元字符实践
<1>特殊字符实践
.实践
实践一:匹配s和d这两个字母之间有两个字符的单词的行:s..d
实践二:匹配s和d这两个字母之间有任意多个字符的单词的行:s.*d
实践三:匹配非空行,并加上行号:"egrep -n '.' zhengze.txt"或"egrep -v -n '^$' zhengze.txt"
实践四:匹配.这个字符的行:\.
[...]实践
实践一:匹配任意一个单个数字的行:[0-9]
实践二:匹配小写字母开头的行:^[a-z]
实践三:匹配一位数字和小写字母构成的两位字符所在的行:[0-9][a-z]
实践四:匹配s和id字母之间要么是a,要么是o的行:s[ao]id或s(a|o)id
实践五:匹配含有[ ]的行:\[.*\]
[^...]实践
实践一:匹配任意一个非数字字符对应的行:[^0-9]
实践二:匹配任意一个非小写字母对应的行:[^a-z]
这里需要注意的是:z zo zoo zooo zoooo zoooooo和food foooood这两行因为有空格,所以匹配出来了
实践三:匹配不是小写字母开头的行:^[^a-z]
实践四:匹配不是字母开头的行:^[^a-zA-Z]
实践五:匹配[^ ]对应的行:\[\^.*\]
\实践
实践一:匹配以.结尾的行:\.$
实践二:匹配\对应的行:\\
( )实践
实践一:匹配oo连续出现3次对应的行:(oo){3}或0{6}
实践二:匹配( )对应的行:\(.*\)
|实践
实践一:匹配no或者neither对应的行:n(o|either)或no|neither
实践二:匹配|对应的行:\|
<2>数量限定符实践
*实践
实践一:匹配zo,其中o出现的次数大于等于0次:zo*或zo{0,}
实践二:匹配所有内容:a*或.*
实践三:匹配至少包含一个a的行:aa*或a{1,}或a+
实践四:匹配至少包含两个连续a的字符串对应的行:aaa*或a{2,}或aa+
实践五:匹配至少包含四个连续a的字符串对应的行:aaaaa*或a{4,}或aaaa+
实践六:匹配*字符对应的行:\*
+实践
实践一:匹配zo,其中o出现的次数大于1次:zo+或zo{1,}或zoo*
实践二:匹配+字符对应的行:\+
?实践
实践一:匹配zo,其中o出现的次数为0,或者是1:zo?或zo{0,1}或zo{,1}
实践二:匹配is或this:(th)?is或(th){0,1}is或(th){,1}is或is|this
实践三:匹配?字符对应的行:\?
{n}实践
实践一:匹配o,其中o出现的次数为2:o{2}
实践二:匹配{ }字符对应的行:\{.*\}
{n,}实践
实践一:匹配o,其中o出现的次数大于2:o{2,}或ooo*或oo+
{,m}实践
实践一:匹配o,其中o出现的次数小于2:o{,2}或o{0,2}
{n,m}实践
实践一:匹配o,其中o出现的次数为大于等于1,小于等于3:o{1,3}
<3>位置限定符实践
^实践
实践一:匹配以hello开头的行:^hello
实践二:匹配与大写“M”开头的行:^M
实践三:匹配^字符对应的行:\^
$实践
实践一:匹配以hello结尾的行:hello$
实践二:匹配以n结尾的行:n$
实践三:匹配hello行:^hello$
实践四:匹配空行,并加上行号:"egrep -n ^$ zhengze.txt"或"egrep -v -n "." zhengze.txt"
实践五:匹配以M或m开头,并且以m或n结尾的行:^[Mm].*[mn]$
实践六:匹配不以M或m开头,并且不以m或n结尾的行:^[^mn].*[^mn]$
实践七:匹配$字符对应的行:\$
\<实践
实践一:匹配以th开头的单词所在的行:\<th或\bth
实践二:匹配\<字符对应的行:\\<
\>实践
实践一:匹配以p结尾的单词所在的行:p\>或p\b
实践三:匹配\>字符对应的行:\\>
\b实践
实践一:匹配以at开头的单词所在的行:\bat或\<at
实践二:匹配以at结尾所在的行:at\b或at\>
实践三:匹配at整个单词所在的行:\bat\b或\>at>\
实践四:匹配\b字符所在的行:\\b
\B实践
实践一:匹配不以at开头的包含at的单词所在的行:\Bat
实践二:匹配不以at结尾的包含at单词所在的行:at\B
实践三:匹配b不是单词at,但是包含at的单词所在的行:\Bat\B
实践四:匹配\B字符所在的行:\\B
6.正则表达式和通配符的区别
<1>正则表达式:用于在文件中匹配符合条件的字符串。正则是包含匹配。grep、awk、sed等命令可以支持正则表达式。
<2>通配符:用于匹配符合条件的文件名,通配符是完全匹配。用来的文件中找内容、文本。ls、find、cp这些命令不支持正则表达式,所以只能用shell自己的通配符来进行匹配。
<3>常见的通配符和通配符字符类:
通配符:
通配符字符类:
注:
通配符[ ]和{ }效果大致一样。但也有下列的4点区别:
<1>通配符[ ]指定的可以是1个,也可以是范围;而通配{ }指定的必须是范围。
<2>通配符[ ]中,指定的必须是单个字符;而通配符{ }中,指定的字符可以不是单个字符。
<3>通配符[ ]中,用“-“指定范围时:针对字母而言,默认忽略大小写,除去最后一个字母的大写;而通配符{ }中,用“..”指定范围时:针对字母而言,不忽略字母大小写。
<4>通配符[ ]指定的范围,可以大;而通配符{ }指定的范围不能大。
<4>环境准备:
<5>常见的通配符实践:
*实践:
实践一:列出所有以file开头的文件名:file*
?实践
实践一:列出所有以file开头,且后面接一个字符的文件名:file?
[ ]实践
实践一:列出所有以file开头的后接1或a或9的文件名:file[1a9]或file{1,a,9}
实践二:列出所有以file开头的后接1-9的文件名:file[1-9]或file{1..9}
实践三:列出所有以file开头的后接小写字母文件名:file[a-z]---错误或file{a..z}---错误或file{a..c}---正确或file[[:lower:]]---正确
[! ]实践和[^ ]实践
实践一:列出所有以file开头的不接1或a或9的单个字符文件名:file[^1a9]或file[!1a9]
实践二:列出所有以file开头的不接1-9的单个字符的文件名:file[^1-9]或file[!1-9]
实践三:列出所有以file开头的不接小写字母的单个字符的文件名:file[^a-z]---错误或file[!a-z]---错误或file[![:lower:]]---正确或file[^[:lower:]]---正确
{ }实践
实践一:列出所有以file开头的后接1-3的文件名:file{1..3}或file[1-3]
实践二:列出所有以file开头的后接1或a的文件名:file{1,a}或file[1a]
[[:alnum:]]实践
实践一:列出所有以file开头的后接一位数字或一位字母的文件名:file[[:alnum:]]
[[:alpha:]]实践
实践一:列出所有以file开头的后接一位字母的文件名:file[[:alpha:]]
[[:digit:]]实践
实践一:列出所有以file开头的后接一位数字的文件名:file[[:digit:]]
[[:lower:]]实践
实践一:列出所有以file开头的后接一位小写字母的文件名:file[[:lower:]]
[[:upper:]]实践
实践一:列出所有以file开头的后接一位大写字母的文件名:file[[:upper:]]
[[:space:]]实践(因为通配符是完全匹配,所以这里不好实践)
[[:punct:]]实践
实践一:列出所有以file开头的后接一位特殊符号的文件名:[[:punct:]]
三.cut命令
1.cut命令的说明
cut命令可以从一个文本文件或文本流中提取文本列。
2.cut命令的格式说明
格式1:cut 参数 文件名
格式2:命令得到的文本 | cut 参数
3.cut命令的主要参数说明
-d参数实践与-f参数实践:
实践一:以:为分隔符,显示/etc/passwd文件中的第一列
实践二:以:为分隔符,显示/etc/passwd文件中的第一列和第三列
实践三:以:为分隔符,显示/etc/passwd文件中的第一列到第三列
-c参数实践
实践一:显示/etc/passwd文件中的第一个字符
实践二:显示/etc/passwd文件中的第一个字符和第三个字符
实践三:显示/etc/passwd文件中的第一个字符到第三个字符
3.cut命令的练习
练习1:获取主机的IP
方法一:
方法二:
练习2:检测172.25.254网段的网络是否通畅,通畅的网段显示up,不通畅的网段显示down
[root@server scripts]# vim ping.sh
#!/bin/bash
ping -c1 -w1 172.25.254.$1 > /dev/null && echo "172.25.254.$1 is up" || echo "172.25.254.$1 is down"
#其中"> /dev/null"表示将其显示的结果导入到垃圾箱中,即不显示过程。
#"&&"表示前面的命令执行正确时,执行"&&"后面的命令。
#"||"表示前面的命令执行错误时,执行"||"后面的命令。
四.sort命令
1.sort命令的说明
sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。
2.sort命令格式说明
格式1:sort [参数] 文件名
格式2:命令得到的文本 | sort [参数]
3.sort命令的主要参数说明
-n参数实践
你有没有遇到过10比2小的情况。我反正遇到过。出现这种情况是由于排序程序将这些数字按字符来排序了,排序程序会先比较1和2,显然1小,所以就将10放在2前面喽。这也是sort的一贯作风。
我们如果想改变这种现状,就要使用-n选项,来告诉sort,“要以数值来排序”!
-r参数实践
sort默认的排序方式是升序,如果想改成降序,就加个-r就搞定了。
-u参数实践
它的作用很简单,就是在输出行中去除重复行。
2和11由于重复被-u选项无情的删除了。
-o参数实践(要注意的是:-o参数必须写在排序的最后面)
由于sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如sort filename > newfile。
但是,如果你想把排序结果输出到原文件中,用重定向可就不行了。
看,竟然将number.txt文件清空了。
就在这个时候,-o选项出现了,它成功的解决了这个问题,让你放心的将结果写入原文件。这或许也是-o比重定向的唯一优势所在。
小总结:如果要保存到其他文件中,使用重定向或者-o参数都可以;但是如果要保存到原文件中,必须使用-o参数。
-t参数实践与-k参数实践
如果有一个文件的内容是这样
这个文件有三列,列与列之间用冒号隔开了,第一列表示水果类型,第二列表示水果数量,第三列表示水果价格。
那么我想以水果数量来排序,也就是以第二列来排序,如何利用sort实现?
幸好,sort提供了-t选项,后面可以设定分隔符。(是不是想起了cut的-d选项,共鸣~~)
指定了分隔符之后,就可以用-k来指定列数了。
我们使用冒号作为间隔符,并针对第二列来进行数值升序排序,结果很令人满意。
3.sort命令的练习:取出/boot目录中的最大的文件对应的文件名
方法一:
方法二:
五.uniq命令
1.uniq命令的说明
uniq命令可以去除排序过的文件中的重复行,因此uniq经常和sort合用。也就是说,为了使uniq起作用,所处理的文本中必须有重复行。
2.uniq命令格式说明
格式1:uniq [参数] 文件名
格式2:命令得到的文本 | uniq [参数]
3.uniq命令的主要参数说明
testfile的内容如下
不加任何参数实践
-u参数实践
-d参数实践
-c参数实践
六.test命令和[ ]命令
1.test命令和[ ]命令的说明
test命令用于检查某个条件是否成立,它可以进行数值,字符串和文件三个方面的测试。
test命令不会自己输出执行的结果,配合$?查询上一条命令是否执行成功,就能够进行判断了。
使用[ ]的时候注意中间的空格,两边都要有两个空格
[ ]与test命令的功能相似,可以进行判断,相比test命令更为便捷
2.test命令和[]命令的应用说明
<1>数值测试(注意:数字和参数之间有空格)
判断的格式:
-gt参数实践:test "$a" -gt "$b"或者[ "$a" -gt "$b" ]
-ge参数实践:test "$a" -ge "$b"或者[ "$a" -ge "$b" ]
-lt参数实践:test "$a" -lt "$b"或者[ "$a" -lt "$b" ]
-le参数实践:test "$a" -le "$b"或者[ "$a" -le "$b" ]
-eq参数实践:test "$a" -eq "$b"或者test "$a" == "$b"或者[ "$a" -eq "$b" ]或者[ "$a" == "$b" ]
-ne/!-eq参数实践:test "$a" -ne "$b"或者test "$a" != "$b"或者[ "$a" -ne "$b"]或者[ "$a" != "Sb" ]
-z参数的实践:test -z "$a"或者[ -z "$a" ]
-n参数的实践:test -n "$a"或者[ -n "$a" ]
-a参数的实践:test "$a" -ne "$b" -a "$a" -lt "$b"或者[ "$a" -ne "$b" -a "$a" -lt "$b" ]
-o参数的实践:test "$a" -ne "$b" -o "$a" -gt "$b"或者[ "$a" -ne "$b" -o "$a" -gt "$b" ]
!参数的实践:test ! "$a" -eq "$b"或者[ ! "$a" -eq "$b" ]
<2>字符串测试(注意:数字和参数之间有空格)
判断的格式:
=参数实践:test "$a" = "$b"或者test "$a" == "$b"或者[ "$a" = "$b" ]或者[ "$a" == "$b" ]
!=参数实践:test "$a" != "$b"或者[ "$a" != "$b" ]
-z参数实践:test -z 字符串或者[ -z 字符串 ]
-n参数实践:test -n 字符串或者[ -n 字符串 ]
-a参数实践:test -n "$str1" -a "$str1" == "$str2"或者[ -n "$str1" -a "$str1" == "$str2" ]
-o参数实践:test -n "$str1" -o "$str1" == "$str2"或者[ -n "$str1" -o "$str1" == "$str2" ]
!参数实践:test ! "$str1" == "$str2"或者[ ! "$str1" == "$str2" ]
<3>文件测试(注意:参数和文件名之间有空格)
判断的格式:
-e参数实践:test -e 文件名或者[ -e 文件名 ]
-f参数实践:test -f 文件名或者[ -f 文件名 ]
-d参数实践:test -d 文件名或者[ -d 文件名 ]
-b参数实践:test -b 文件名或者[ -b 文件名 ]
-c参数实践:test -c 文件名或者[ -c 文件名 ]
-S参数实践:test -S 文件名或者[ -S 文件名 ]
-L参数实践:test -L 文件名或者[ -L 文件名 ]
-r参数实践:test -r 文件名或者[ -r 文件名 ]
-w参数实践:test -w 文件名或者[ -w 文件名 ]
-x参数实践:test -x 文件名或者[ -x 文件名 ]
-a参数实践:
-o参数实践:
!参数实践:
3.test命令和[ ]命令的练习
练习一:
判断输入的数字是否在10以内
1.输入是否为空
2.是否在10以内
3.1<$a<10 --> yes
4.$a<1 $a>10 --> no
[root@server scripts]# vim judge.sh
#!/bin/bash
read -p "请输入一个数字:" a
[ -n "$a" ] && echo "输入的数字不为空值" ||
{
echo "输入的数字为空值"
exit 1
} #前面的命名执行错误时,执行此语句体。因为如果执行错误,就不能再继续执行下面的语句了,所以u这里必须有"exit 1"这个语句,跳出来。
[ "$a" -gt 1 -a "$a" -lt 10 ] && echo "yes" || echo "no"
练习二:
交互式输入参数来判断文件类型
交互式输入文件来判断文件类型
七.sed命令(一行一行的匹配)
/wangcp-/p/6756377.html
1.sed命令的说明
在编写shell脚本的过程中,我们经常需要使用sed流编辑器和awk对文本文件进行处理。
sed (stream editor)是一种在线编辑器,它一次处理一行内容。sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。
sed用于一次性处理所有的编辑任务,尤为高效,为用户节省了大量的时间,sed适用于以下三种场合:
1、编辑相对交互文本编辑器而言太大的文件;
2、编辑命令太复杂,在交互式文本编辑器中难以输入的情况;
3、对文件扫描一遍,但是需要执行多个编辑函数的情况;
sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。
前面说到sed不会修改文件,那么现在我们可以知道是为什么了?是因为sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。
因此,如果需要保存改动内容,需要将输出重定向到另一个文件,可以使用下面格式的命令:
sed 'sed命令' input_file > result_file
该命令将sed 命令对input-file的更改保存到result-file中,“>”符号是重定向符号;
2.sed命令的使用格式
(1)命令行格式:
<1>sed [参数] '命令' 文件名 #一般用单引号引起命令
<2>命令得到的文本 | sed [参数] '命令' #一般用单引号引起命令
(2)脚本格式:sed -f 脚本的文件名 文件名:命令还可以写在一个脚本文件里调用
(3)sed脚本,格式为:./sed 脚本文件 输入文件
我们经常使用的是第一种命令行格式。
参数中有 -n 、-i、-e是比较常用的。命令:行定位或或正则表达式+sed命令(操作)。其中s,g命令的格式比较特殊,需要单独记。(1)这里的行定位要么是数字(单个数字;用","表示一个连续的范围;用";"表示和),要么是$。(2)这里的正则表达式,要么是egrep命令中的普通的字符串(特殊的正则表达式),要么是正则表达式,有的特殊符号需要转义的要使用“\”。
可以在行定位和命令之间加!表示逻辑非。
sed命令标识对文本进行如何处理。如打印(p命令)、删除(d命令)、追加(a命令)、插入(i命令)、替换(c命令,s命令,g命令)等
3.sed命令的主要参数和主要命令的说明
p命令实践和-n参数的实践:
实践一:地址是一个数字,则表示行号;是“$"符号,则表示最后一行。
[root@server scripts]# sed -n '1p' girl.txt #只打印第一行。-n:取消默认打印设置(全部打印),p:打印。若不带-n选项,则不仅仅打印第1行,还会打印input的全部内容;
I am a girl
[root@server scripts]# sed -n '$p' girl.txt #只打印最后一行
my god , i am a girl not a gill!
实践二:地址是用//来表示的,则表示打印匹配包含//之间的关键字的行。
[root@server scripts]# sed -n '/my/p' girl.txt #只打印匹配包含my的行
my qq num is 123456.
my blog is
my god ,i am a girl not a gill!
[root@server scripts]# sed -n '/2/p' girl.txt #只打印匹配包含2的行
my qq num is 123456.
not 0123456.
[root@server scripts]# sed -n '/:/p' /etc/fstab 或者sed -n '/\:/p' /etc/fstab #打印匹配包含:的行。\表示转义
# Created by anaconda on Wed May 7 01:22:57
实践三:只显示指定行范围的文件内容。地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内)。范围可以用数字、正则表达式、或二者的组合表示。
[root@server scripts]# sed -n '2,4p' girl.txt #只打印文件的第2行到第4行内容
I come from Shanxi
my qq num is 123456.
[root@server scripts]# sed -n '2,4!p' girl.txt #只打印不是第2行到第4行的内容
I am a girl
not 0123456.
my blog is
my god ,i am a girl not a gill!
[root@server scripts]# sed -n '/my/,6p' girl.txt#只打印匹配包含my的行,及第一个出现my的行到第6行之间的内容
my qq num is 123456.
not 0123456.
my blog is
my god ,i am a girl not a gill!
实践四:只显示指定行的文件内容。地址是分号分隔的
[root@server scripts]# sed -n '2p;6p' girl.txt #打印第2行和第6行的内容
I come from Shanxi
not 0123456.
实践五:sed命令与正则表达式的结合。正则表达式要用//括起来。
[root@server scripts]# sed -n '/^#/p' /etc/fstab #只打印以#开头的行
#
# /etc/fstab
# Created by anaconda on Wed May 7 01:22:57
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
[root@server scripts]# sed -n '/^#/!p' /etc/fstab #只打印不以#开头的行
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 / xfs defaults 1 1
d命令实践(与p命令的用法完全相同):删除之后,打印出来的内容是删除完成之后的内容
实践一:地址是一个数字,则表示行号;是“$"符号,则表示最后一行。
[root@server scripts]# sed '1d' girl.txt #删除第一行,打印剩下的全部内容
I come from Shanxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i am a girl not a gill!
[root@server scripts]# sed '$d' girl.txt #删除最后一行内容,打印剩下的全部内容
I am a girl
I come from Shanxi
my qq num is 123456.
not 0123456.
my blog is
实践二:地址是用//来表示的,则表示打印匹配包含//之间的关键字的行。
[root@server scripts]# sed '/my/d' girl.txt #删除包含my的行,打印剩下的全部内容
I am a girl
I come from Shanxi
not 0123456.
[root@server scripts]# sed '/2/d' girl.txt #删除包含2的行,打印剩下的全部内容
I am a girl
I come from Shanxi
my blog is
my god ,i am a girl not a gill!
[root@server scripts]# sed '/:/d' /etc/fstab或者sed '/:\/d' /etc/fstab #删除包含:的行,打印剩下的全部内容
#
# /etc/fstab
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 / xfs defaults 1 1
实践三:只显示指定行的文件内容。地址是分号分隔的
[root@server scripts]# sed '2d;6d' girl.txt #删除第2行和第6行的内容,打印剩下的全部内容
I am a girl
my qq num is 123456.
my blog is
my god ,i am a girl not a gill!
实践四:只显示指定行范围的文件内容。地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内)。范围可以用数字、正则表达式、或二者的组合表示。
[root@server scripts]# sed '2,4d' girl.txt #删除第二行到第四行的内容,打印剩下的全部内容
I am a girl
not 0123456.
my blog is
my god ,i am a girl not a gill!
[root@server scripts]# sed '2,4!d' girl.txt #删除不是第二行到第四行的内容,打印剩下的全部内容
I come from Shanxi
my qq num is 123456.
[root@server scripts]# sed '/my/,6d' girl.txt #删除包含my的行,及第一个出现my的行到第6行之间的内容,打印剩下的全部内容
I am a girl
I come from Shanxi
实践五:sed命令与正则表达式的结合。正则表达式要用//括起来。
[root@server scripts]# sed '/^#/d' /etc/fstab #删除以#开头的行,打印剩下的全部内容
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 / xfs defaults 1 1
[root@server scripts]# sed '/^#/!d' /etc/fstab #删除不以#开头的行,打印剩下的全部内容
#
# /etc/fstab
# Created by anaconda on Wed May 7 01:22:57
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
[root@server scripts]# sed '/^$/d' girl.txt #删除空行,打印剩下的全部内容
I am a girl
I come from Shanxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i am a girl not a gill!
a命令实践:追加的文本位于sed命令的下方另起一行
实践一:追加一行
[root@server scripts]# sed '/my/aworld' girl.txt #在含有my的行的下一行追加world。
I am a girl
I come from Shanxi
my qq num is 123456.
world
not 0123456.
my blog is
world
my god ,i am a girl not a gill!2
world
实践二:追加多行
[root@server scripts]# sed '/my/aredhat\nlinux' girl.txt #在含有my的行的下一行追加redhat和linux两行内容。\n表示换行
I am a girl
I come from Shanxi
my qq num is 123456.
redhat
linux
not 0123456.
my blog is
redhat
linux
my god ,i am a girl not a gill!
redhat
linux
a\命令实践:追加的文本位于sed命令的下方另起一行
实践一:追加一行
[root@server scripts]# sed '/my/a\ #在含有my的下一行追加world
> world' girl.txt
I am a girl
I come from Shanxi
my qq num is 123456.
world
not 0123456.
my blog is
world
my god ,i am a girl not a gill!
world
实践二:追加多行
如果要追加的内容超过一行,可以通过a\命令。每一行都必须以反斜线结束,最后一行除外。最后一行将以引号和文件名结束。
[root@server scripts]# sed '/my/a\ #在含有my的下一行追加redhat和linux两行内容。
> redhat\
> linux' girl.txt
I am a girl
I come from Shanxi
my qq num is 123456.
redhat
linux
not 0123456.
my blog is
redhat
linux
my god ,i am a girl not a gill!
redhat
linux
i命令实践
实践一:插入一行
[root@server scripts]# sed '/my/iworld' girl.txt #在含有my的行的前面一行追加world这一行
I am a girl
I come from Shanxi
world
my qq num is 123456.
not 0123456.
world
my blog is
world
my god ,i am a girl not a gill!
实践二:插入多行
[root@server scripts]# sed '/my/iredhat\nlinux' girl.txt #在含有my的行的前面一行追加redhat和linux两行。\n表示换行
I am a girl
I come from Shanxi
redhat
linux
my qq num is 123456.
not 0123456.
redhat
linux
my blog is
redhat
linux
my god ,i am a girl not a gill!
i\命令实践
实践一:插入一行
[root@server scripts]# sed '/my/i\ #在含有my的行的前面一行追加world这一行
> world' girl.txt
I am a girl
I come from Shanxi
world
my qq num is 123456.
not 0123456.
world
my blog is
world
my god ,i am a girl not a gill!
实践二:插入多行
[root@server scripts]# sed '/my/i\ #在含有my的行的前面一行追加redhat和linux两行
> redhat\
> linux' girl.txt
I am a girl
I come from Shanxi
redhat
linux
my qq num is 123456.
not 0123456.
redhat
linux
my blog is
redhat
linux
my god ,i am a girl not a gill!
c命令实践
实践一:替换为一行
[root@server scripts]# sed '/my/chello' girl.txt #将含有my的行替换为hello行
I am a girl
I come from Shanxi
hello
not 0123456.
hello
hello
实践二:替换为多行
[root@server scripts]# sed '/my/chello\nworld' girl.txt#将含有my的行替换为hello和world两行。\n表示换行
I am a girl
I come from Shanxi
hello
world
not 0123456.
hello
world
hello
world
c\命令实践
实践一:替换为一行
[root@server scripts]# sed '/my/c\ #将含有my的行替换为hello行
> hello' girl.txt
I am a girl
I come from Shanxi
hello
not 0123456.
hello
hello
实践二:替换为多行
[root@server scripts]# sed '/my/c\ #将含有my的行替换为hello和world两行
> hello\
> world' girl.txt
I am a girl
I come from Shanxi
hello
world
not 0123456.
hello
world
hello
world
s命令实践
[root@server scripts]# sed 's/a/b/' girl.txt #将带a的字符串对应的行的第一个字符串替换为带b的字符串
I bm a girl
I come from Shbnxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i bm a girl not a gill!
[root@server scripts]# sed 's/\//#/' /etc/fstab #将带/的字符串对应的行的第一个字符串替换为#。其中\表示转义
#
# #etc/fstab
# Created by anaconda on Wed May 7 01:22:57
#
# Accessible filesystems, by reference, are maintained under '#dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and#or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 # xfs defaults 1 1
g命令实践
[root@server scripts]# sed 's/a/b/g' girl.txt #将带a的字符串全部替换为b
I bm b girl
I come from Shbnxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i bm b girl not b gill!
[root@server scripts]# sed 's/\//#/g' /etc/fstab #将带/的字符串的所有替换为#。其中\表示转义
#
# #etc#fstab
# Created by anaconda on Wed May 7 01:22:57
#
# Accessible filesystems, by reference, are maintained under '#dev#disk'
# See man pages fstab(5), findfs(8), mount(8) and#or blkid(8) for more info
#
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 # xfs defaults 1 1
-i参数的实践:直接在原文件进行操作,不输出任何内容,但是修改了原文件的内容。结合前面的命令使用。这里只是列举了sed的一个命令。
保存修改的两种方法:两种方法的区别在于(方法一是保存到原文件,而方法二是保存到别的文件)
方法一:使用-i参数。保存到原文件
[root@server scripts]# cat girl.txt
I am a girl
I come from Shanxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i am a girl not a gill!
[root@server scripts]# sed -i 's/a/b/' girl.txt #在原文件中进行修改,将带a的字符串对应的每行的第一个字符串改为b
[root@server scripts]# cat girl.txt
I bm a girl
I come from Shbnxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i bm a girl not a gill!
方法二:使用重定向。保存到别的文件
[root@server scripts]# sed 's/a/b/' girl.txt > girl2.txt
[root@server scripts]# cat girl2.txt
I bm a girl
I come from Shbnxi
my qq num is 123456.
not 0123456.
my blog is
my god ,i bm a girl not a gill!
-e参数的实践:
-e是编辑命令,用于sed执行多个编辑任务的情况下。在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。
[root@server scripts]# sed -e '1d' -e '/qq/ahello' girl.txt #选项-e用于进行多重编辑。第一重编辑删除第1行。第二重编辑:在带有qq的行的后一行追加hello。因为是逐行进行这两项编辑(即这两个命令都在模式空间的当前行上执行),所以编辑命令的顺序会影响结果。
I come from Shanxi
my qq num is 123456.
hello
not 0123456.
my blog is
my god ,i am a girl not a gill!
4.sed命令的练习:
编写一个脚本,实现的功能是:安装apache,使得apache开机自启动,并将apache的默认侦听端口改为8080
方法一:
脚本内容
脚本执行结果
方法二:
脚本内容
脚本执行结果
比较上述两种方法:方法一只能执行一次(因为是拿字符串80进行匹配的,下次执行脚本时,可能就找不到80,所以会出现错误),而方法二可以执行多次(方法二不是拿字符串进行匹配的)。所以方法二更好一些
八.awk命令(一行一行的匹配)
1.awk命令的说明
awk也是一个文本与数据处理工具,但是awk是可编程的,更灵活强大。
awk为程序员提供了完整的编程模型,awk程序由一个主输入循环(main input loop)维持,主输入循环反复执行,直到终止条件被触发。awk已经搭好了主输入循环框架,程序员写的代码被嵌入到主输入循环框架中执行。例如在java中,程序员需要写一个main函数,打开文件、读取文件行、进行相应处理,关闭文件,awk自动完成了上述步骤。
awk还定义了两个特殊的字段,BEGIN和END,BEGIN用于在主输入循环之前执行,即在未读取文件行之前执行,END在主输入循环之后执行,即在读取输入行完毕后执行。
awk是以文件的一行为处理单位的。以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。如下所示:
[root@server scripts]# cat test
this | is | a | file
$1 $2 $3 $4
2.awk命令的使用格式
格式与sed差不多:
(1)命令行格式:
<1>awk [参数] '命令' 文件名 #一般用单引号引起命令
<2>命令得到的文本 | awk [参数] '{命令}' #一般用单引号引起命令
而{命令}的格式:1.[模式]{awk操作命令}。即模式可有可无。2.java中的if条件判断语句,for循环语句,while循环语句+awk操作命令。
模式:正则表达式和逻辑判断式。其中正则表达式,要用//括起来
awk操作命令:内置函数print与内置变量的结合
(2)脚本格式:awk -f 脚本的文件名 文件名
我们经常使用的是第一种命令行格式。
参数中-F参数是比较常用的,awk操作命令中print是比较常用的。
3.awk命令的主要参数,主要操作命令和awk命令中的逻辑运算符的说明
内置变量$0与什么都不接与接空格实践
[root@server scripts]# awk '{print $0}' girl.txt #输出整个文件的内容
I am a girl
I come from Shanxi
my qq num is 123456.
not 0123456.
my alog is
my god ,i am a girl not a gill!
[root@server scripts]# awk '{print}' girl.txt #输出整个文件的内容
I am a girl
I come from Shanxi
my qq num is 123456.
not 0123456.
my alog is
my god ,i am a girl not a gill!
[root@server scripts]# awk '{print }' girl.txt #输出整个文件的内容
I am a girl
I come from Shanxi
my qq num is 123456.
not 0123456.
my alog is
my god ,i am a girl not a gill!
内置变量$n(n>0)实践
实践一:显示一个字段的内容
[root@server scripts]# awk '{print $1}' girl.txt #以空格为分隔符,输出每行的第一个字段的内容
I
I
my
not
my
my
实践二:同时显示多个字段的内容
[root@server scripts]# awk '{print $1,$2,$4}' girl.txt #以空格为分隔符,同时输出每行的第一个字段,第二个字段和第四个字段的内容
I am girl
I come Shanxi
my qq is
not 0123456.
my alog
my god am
内置变量NR和内置变量FILENAME实践
[root@server scripts]# awk '{print FILENAME,NR}' girl.txt #输出当前操作的文件名,和当前操作的行号,文件中有几行,默认就输出几个文件名
girl.txt 1
girl.txt 2
girl.txt 3
girl.txt 4
girl.txt 5
girl.txt 6
girl.txt 7
girl.txt 8
girl.txt 9
girl.txt 10
内置变量NF实践
[root@server scripts]# awk '{print NR,NF}' girl.txt #输出当前操作的行号,以及当前以空格为分割符的字段的个数即每列的列数。文件中有几行,默认就输出几个列数。
1 4
2 4
3 0
4 5
5 0
6 2
7 0
8 4
9 0
10 9
[root@server scripts]# awk '{print "第"NR"行","有"NF"列"}' girl.txt#尤其注意"第"NR"行","有"NF"列"的写法
第1行 有4列
第2行 有4列
第3行 有0列
第4行 有5列
第5行 有0列
第6行 有2列
第7行 有0列
第8行 有4列
第9行 有0列
第10行 有9列
参数-F的实践:与前面的内置参数和内置命令结合使用,这里只列举了一个命令,别的命令的结合使用类比这个例子即可
[root@server scripts]# awk -F ":" '{print $1,$3}' /etc/passwd #指定以:为分隔符,输出每行的第一个和第三个字段
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14
扩展:同时执行多条命令的实践(第二条命令的结果位于每个第一条命令的结果之下,第三条命令的结果位于每个第二条命令的结果之下,以此类推)
[root@server scripts]# awk '{print $1;print $2}' girl.txt #同时打印每行的第一个字段和第二个字段。且第二个字段的内容均位于每个第一个字段的内容下面
I
am
I
come
my
not
0123456.
my
alog
my
god
逻辑判断式的实践
[root@server scripts]# awk 'NR==2{print $0}' girl.txt #打印文件第二行的内容
I come from Shanxi
[root@server scripts]# awk 'NR%2==0{print}' girl.txt #打印偶数行的内容
I come from Shanxi
my qq num is 123456.
not 0123456.
my alog is
my god ,i am a girl not a gill!
[root@server scripts]# awk 'NR>=3 && NR<=5{print}' girl.txt #打印第三行到第五行的内容
my qq num is 123456.
正则表达式的实践:其中正则表达式的内容要用//括起来。
[root@server scripts]# awk '/i$/{print}' girl.txt #打印以i结尾的行对应的内容
I come from Shanxi
4.特殊字段BEGIN和END的常规用法
BEGIN{ }:读入第一行文本之前执行的语句,一般用来初始化操作。BEGIN{ }括号里面的语句,既可以计算数学表达式,也可以只是普通的打印相应的内容,也可以既计算表达式,也打印相应的内容。
{ }:逐行处理,逐行读取文本执行相应的处理,是最常见的编辑命令。{ }部分的内容同前面的{命令}的格式。只是这里可以少掉awk操作命令的内容,只有模式。
END{ }:处理完最后一行文本后执行,一般用来处理输出结果。END{ }括号里面的语句,既可以计算表达式,也可以只是普通的打印相应的内容。
实践一:后面接文件名,文件只对中间的{ }里面的内容起作用
这三个语句可以同时出现,也可以单独出现,也可以组合出现。
[root@server scripts]# awk 'BEGIN{print "redhat"} {print NR;print} END{print "linux"}' girl.txt #文件开头打印redhat,末尾打印linux,中间打印行号和内容
redhat
1
I am a girl
2
I come from Shanxi
3
4
my qq num is 123456.
5
6
not 0123456.
7
8
my alog is
9
10
my god ,i am a girl not a gill!
linux
[root@server scripts]# awk 'BEGIN{a=20;print a-2} NR==2{print $1} END{a=20;print a/2}' girl.txt #文件开头打印20-2的结果值,末尾打印20/2的结果值,中间打印第二行的第一个字段的内容
18
I
10
实践二:后面不接文件名,此时只能BEGIN单独出现
[root@server scripts]# awk 'BEGIN{a=10;print a+10}' #计算a+10的值
20
5.特殊BEGIN和END的特殊用法
实践一:单独统计一个文件中的数量。此时必须三个语句同时连用
[root@server scripts]# awk 'BEGIN{i=0} {i+=NF} END {print i}' girl.txt #统计文件中的总字段数。默认一行一行的进行统计。
28
实践二:与if单分支语句的结合,统计一个文件中数量。此时必须三个语句同时连用
[root@server scripts]# awk -F ":" 'BEGIN{i=0} {if($7~/bash$/){i++}} END{print i}' /etc/passwd #统计登陆shell为bash的用户的个数。因为默认是一行一行的进行统计,所以,即使不是循环也能统计出数量。
2
或
[root@server scripts]# awk 'BEGIN{i=0} {if(/bash$/){i++}} END{print i}' /etc/passwd
2
实践三:与if双分支语句的结合,统计一个文件中的数量。此时必须三个语句同时连用
[root@server scripts]# awk -F ":" 'BEGIN{i=0;j=0} {if($3<=500){i++}else{j++}} END{print i,j}' /etc/passwd #统计uid小于500和uid大于500的用户的个数。因为默认是一行一行的进行统计,所以,即使不是循环也能统计出数量。
32 9
实践四:与for循环语句的结合。后面不加文件名,所以只能单独使用BEGIN
[root@server scripts]# awk 'BEGIN{for(i=0;i<=5;i++){print i}}' #打印0-5之间的数字
0
1
2
3
4
5
实践五:与while循环语句的结合
[root@server scripts]# awk 'BEGIN{i=0} {while(i<=5){print i;i++}}' /etc/fstab #打印0-5之间的数字。因为后面有{ }语句,所以后面必须加文件名,其实文件名是不起作用的,随便给个文件名即可。
0
1
2
3
4
5
6.awk命令的练习:
列出uid小于等于2的用户信息
正确解法一:
[root@server scripts]# awk -F ":" '$3<=2 && $3>=0{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
正确解法二:
[root@server scripts]# awk -F ":" '{if($3<=2 && $3>=0){print $1,$3}}' /etc/passwd
root 0
bin 1
daemon 2
错误解法:
[root@server scripts]# awk -F ":" 'BEGIN{if($3<=2 && $3>=0){print $1,$3}}' /etc/passwd #因为后面的文件名只对中间的语句体{ }起作用,所以该语句是错误的。
九.seq命令
<1>seq n:默认起始值为1,步长为1
[root@server scripts]# seq 5 #打印1-5之间的数字,其中5可以换为任意的数字,比如换为n,则表示打印1-n之间的数字。
1
2
3
4
5
<2>seq 起始值 步长 终止值
[root@server scripts]# seq 2 2 7 #打印2-7之间的数字,步长为2
2
4
6
<3>seq 终止值 步长 起始值 #值的注意的是:这里的步长应该是负数,因为相当于倒着数数。
[kiosk@foundation83 ~]$ seq 10 -1 1 #倒着打印10-1之间的数(这里的步长为-1)
10
9
8
7
6
5
4
3
2
1
[kiosk@foundation83 ~]$ seq 10 -2 1 #倒着打印10-1之间的偶数(这里的步长为-2)
10
8
6
4
2
<4>seq的-w参数
[root@server scripts]# seq -w 11 #产生的数字的位数是11的位数(即两位),不够的用0来补
01
02
03
04
05
06
07
08
09
10
11
[root@server scripts]# seq -w 100 #产生的数字的位数是100的位数(即三位),不够的用0来补
001
002
003
004
005
006
......
090
091
092
093
094
095
096
097
098
099
100