Linux下的shell编程之文本处理命令(grep,egrep,cut,sort,uniq,test,[ ],sed,awk),正则表达式及seq命令

一.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指定显示前几行

-i参数实践

-v参数实践

-c参数实践


-n参数实践

-q参数实践

-o参数实践

-m参数实践L

2.egrep命令(相当于grep   -E)的使用

同grep命令的使用,egrep是grep的扩展。

grep能执行的命令,egrep一定能执行。

但是,有时候,egrep能执行的命令,grep是不能执行的。

我们一般使用egrep。

二.正则表达式(这里的实践以egrep和正则表达式的结合为例。别的命令与正则表达式的结合的使用类比即可。)

https://www.cnblogs.com/TsingYoung/p/8249782.html

1.正则表达式的说明

        正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

        正则表达式是由普通字符(例如字符 a 到 z)以及元字符组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配

       支持正则表达式的工具有:

  1. 用于匹配文本行的grep工具族(grep和egrep)
  2. 用于改变输入流的sed流编辑器;
  3. 用于处理字符串的语言,如awkpython,perl,Tel等语言;
  4. 文本查看程序,或分页程序,more,page,less
  5. 文本编辑器,如ed,vi,emacs,vim

2.普通字符

        由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。

<1>非打印字符

非打印字符含义
\f匹配一个换页符(清楚屏幕)

\n

匹配一个换行符(Newline)
\r匹配一个回车符(Carriage  return)
\t匹配一个水平制表符(Horiziontal  tab):默认空三个空格

\v

匹配一个垂直制表符(Vertical  tab)
\s匹配任何空白字符,包括换页符,换行符,回车符和制表符。等加于[\f\n\r\t\v]
\S匹配任何非空白字符。等价于[^\f\n\r\t\v]

3.元字符

<1>元字符介绍

         元字符一般分为特殊字符,数量限定符和位置限定符。

<2>特殊字符

        下面介绍常见的特殊字符。

特殊字符

含义举例说明
.匹配任意一个非换行符的字符。

"s..d" 匹配在s和d这两个字母之间一定有两个字符的单词
"s.*d" 匹配在s和d字母之间有任意字符
".*" 匹配所有内容

要匹配 .,请使用 \.

[...]方括号表达式,匹配方括号内任意一个字符。

"[0-9]" 匹配任意一位数字,

"^[a-z]" 匹配小写字母开头的行
"[0-9][a-z]" 匹配一位数字和小写字母构成的两位字符。
"s[ao]id" 匹配s和id字母中,要么是a,要么是o

要匹配[...],请使用\[.*\]

[^...]如果^符号位于方括号的开始,则具有相反的含义。

"[^0-9]" 匹配任意一位非数字字符,
"[^a-z]" 表示任意一位非小写字母
"^[^a-z]"  匹配不是小写字母开头的行
"^[^a-zA-Z]" 匹配不是字母开头的行

要匹配[^...],请使用\[\^.*\]

\转义字符:用于打开或者关闭后续字符的特殊含义。

"\.$" 匹配使用"."结尾的行

要匹配\,请使用\\

( )将正则表达式的一部分括起来组成一个单元,可以对整个单元使用数量限定符。

(oo){3},匹配oo连续出现3次的字符串

要匹配( ),请使用\(.*\)

|连接两个字表达式,表示或的关系

n(o|either),匹配no或者neither

要匹配|,请使用\|

<3>数量限定符

        数量限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{,m}或{n,m}共7种。

        正则表达式的数量限定符有:

数量限定符含义举例说明
*匹配前面的子表达式连续出现零次或多次。

例如,zo* 能匹配 “z” 以及 “zoo”等等。* 等价于{0,}

"a*" 匹配所有内容,包括空白行 
"aa*" 匹配至少包含一个a的行
"aaa*" 匹配至少包含两个连续a的字符串
"aaaaa*"匹配至少包含4个连续a的字符串

要匹配 * 字符,请使用 \*。

+匹配前面的子表达式连续出现一次或多次。

例如,’zo+’ 能匹配 “zo” 以及 “zoo”等等,但不能匹配 “z”。+ 等价于 {1,}

要匹配 + 字符,请使用 \+。

?匹配前面的子表达式连续出现零次或一次。或指明一个非贪婪限定符

例如,”(th)?is” 可以匹配 “is” 或 “this” 中的”is” 。? 等价于 {0,1}

要匹配 ? 字符,请使用 \?。

{n}n 是一个非负整数。连续出现匹配确定的 n 次。

例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。

要匹配{...},请使用\{.*\}

{n,}n 是一个非负整数。至少连续出现匹配n 次。例如,’o{2,}’ 不能匹配 “Bob” 中的 ‘o’,但能匹配 “foooood” 中的所有o。’o{1,}’ 等价于 ‘o+’。’o{0,}’ 则等价于 ‘o*’
{,m}m是一个非负整数。至多连续出现匹配m次。即0-m次例如,’o{,2}’能匹配“Bob” 中的 ‘o’等等,能匹配 “foooood” 中的前两个 o。但不能匹配 “foooood” 中的所有 o。
{n,m}m 和 n 均为非负整数,其中n <= m。最少连续出现匹配 n 次且最多连续出现匹配 m 次。例如,”o{1,3}” 将匹配 “foooood” 中的前三个 o。’o{0,1}’ 等价于 ‘o?’。请注意在逗号和两个数之间不能有空格。

<4>位置限定符

位置限定符含义举例说明
^匹配行首。

"^hello" 匹配以hello开头的行
"^M" 匹配以大写“M”开头的行

要匹配 ^ 字符本身,请使用 \^。

$

匹配行尾。

"hello$" 匹配以hello结尾的行 
"n$" 匹配以小写“n”结尾的行

"^hello$"匹配hello这一行
"^$" 匹配空白行

"^[Mm].*[mn]$"匹配以M或m开头,并且以m或n结尾的行

"^[^Mm].*[^mn]$"匹配不以M或m开头,并且不以m或n结尾的行

要匹配 $字符本身,请使用 \$。
\<匹配单词开头的位置

\<th匹配...this...,但不匹配tenth等

要匹配\<字符本身,请使用\\<。

\>匹配单词词尾的位置

p\>匹配...leap...,但不匹配parent等

要匹配\>字符本身,请使用\\>。

\b匹配单词的开头或结尾的位置

\bat匹配以at开头的单词

at\b匹配以at结尾的单词

\bat\b匹配...at...,但不匹配cat,batch等

要匹配\b字符本身,请使用\\b。

\B匹配非单词开头或结尾的位置

\Bat匹配不以at开头的单词

at\B匹配不以at结尾的单词

\Bat\B匹配battery,但不匹配attend,hat等

要匹配\B字符本身,请使用\\B。

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>常见的通配符和通配符字符类:

        通配符:

通配符含义
*匹配任意字符(0个或多个)
?匹配任意一个字符(1个)
[ ]与?相似,可以匹配中括号内的一个字符(1个),也可以用“-“进行范围指定(范围)

[! ]或[^ ]

逻辑非,匹配不是中括号内的一个字符(1个),也可以用“-“进行范围指定(范围)。与[ ]意思相反
{ }匹配大括号内的字符(不止1)个,必须用“..“进行范围指定(范围),或者用“,“进行范围指定(范围)
[[:class:]]匹配任意一个属于指定字符类中的字符

        通配符字符类:

字符类含义
[ :alnum: ]匹配任意一个字母或数字(1个)
[ :alpha: ]匹配任意一个字母(1个)
[ :digit: ]匹配任意一个数字(1个)
[ :lower: ]匹配任意一个小写字母(1个)
[ :upper: ]匹配任意一个大写字母(1个)
[ :space: ]匹配一个空格(1个)
[ :punct: ]匹配单个特殊符号(1个)

注:

通配符[ ]和{ }效果大致一样。但也有下列的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一起连用。
-f依据-d的分隔符,将一端信息分割成为很多段。用-f指定要取出的段数
-c以字符(character)为单位,取出固定字符区间

-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纯数字排序<仅仅数字可用>
-r倒序<数字,字母均可用>
-u去掉重复的行<数字,字母均可用>
-o输出到指定文件中<数字,字母均可用>
-t指定分割符,一般与-k选项一起用<数字,字母均可用>
-k指定要排序的列<数字,字母均可用>

-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命令的主要参数说明

参数参数说明
 不加任何参数,默认去重
-u显示文本中不重复的各行
-d只显示重复的行
-c显示输出中,在每行行首加上本行在文本中出现的次数

testfile的内容如下

不加任何参数实践

-u参数实践

-d参数实践

-c参数实践

六.test命令和[ ]命令

1.test命令和[ ]命令的说明

        test命令用于检查某个条件是否成立,它可以进行数值,字符串和文件三个方面的测试。

        test命令不会自己输出执行的结果,配合$?查询上一条命令是否执行成功,就能够进行判断了。

        使用[  ]的时候注意中间的空格,两边都要有两个空格

        [  ]与test命令的功能相似,可以进行判断,相比test命令更为便捷

2.test命令和[]命令的应用说明

<1>数值测试(注意:数字和参数之间有空格)

判断的格式:

符号参数含义英文
>-gt大于grant  than
>=-ge大于等于grant  equal
<-lt小于less  than
<=-le小于等于less  equal
==-eq/==等于equal
!=-ne/!=不等于not  equal
 -z长度为0则为真,即为空值 
 -n长度不为0则为真,即不为空值 
 -a 
 -o 
 !逻辑非 

-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>字符串测试(注意:数字和参数之间有空格)

判断的格式:

参数说明
=/==相等则为真
!=不相等则为真
-z  字符串字符串的长度为0则为真
-n  字符串字符串的长度不为0则为真
-a
-o
!逻辑非

=参数实践: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   文件名文件存在则为真
-f    文件名文件存在且文件为普通文件则为真
-d    文件名文件存在且文件为目录则为真
-b   文件名文件存在且文件为块设备则为真
-c   文件名文件存在且文件是字符设备则为真
-S   文件名文件存在且文件为套接字则为真
-L    文件名文件存在且文件为软链接则为真
-r     文件名文件存在且文件可读则为真(针对文件的拥有者而言)
-w    文件名文件存在且文件可写则为真(针对文件的拥有者而言)
-x    文件名文件存在且文件可执行则为真(针对文件的拥有者而言)
-a
-o
!逻辑非

-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命令(一行一行的匹配)

https://www.cnblogs.com/wangcp-2014/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命令的主要参数和主要命令的说明

参数参数说明
-e进行多项编辑,即对输入行应用多条sed命令时使用
-i直接在原文件上进行操作
-n 取消默认的输出
-f

指定sed脚本的文件名

sed命令sed命令说明
p打印一行<与-n参数连用>
d删除一行<不与-n参数连用>。d命令的使用与p命令完全相同
a在当前行后添加文本
a\在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“\”续行
i在当前行前添加文本
i\在当前行之前插入文本。多行时除最后一行外,每行末尾需用"\"续行
c替换当前行的文本
c\用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用"\"续行
s用一个字符串替换另一个
g在行内进行全局替换。一般和s一起连用

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 http://www.girl.com
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 2014

实践三:只显示指定行范围的文件内容。地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内)。范围可以用数字、正则表达式、或二者的组合表示。

[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 http://www.girl.com

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 http://www.girl.com
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 2014
#
# 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 http://www.girl.com

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 http://www.girl.com

 

实践二:地址是用//来表示的,则表示打印匹配包含//之间的关键字的行。

[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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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 2014
#
# 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 http://www.girl.com
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 http://www.girl.com
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 http://www.girl.com
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 http://www.girl.com
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 http://www.girl.com
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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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 2014
#
# 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 http://www.girl.com

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 2014
#
# 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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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命令中的逻辑运算符的说明

参数参数说明
-F  fsfs指定输入分隔符,不指定默认是空格(几个空格都无所谓,当作是一个空格)
-f   scriptfile从脚本文件中读取awk命令
-v   var=value赋值一个用户定义变量,将外部变量传递给awk
awk操作命令之内置函数awk操作命令之内置函数说明
print打印
awk操作命令之内置变量awk操作命令之内置变量说明
什么都不接,或者接空格表示整个当前行,同$0
$0表示整个当前行
$1表示每行第一个字段
$2表示每行第二个字段
$n(n>0)以此类推,表示每行第n隔字段
NR每行的行号
NF每行的字段数,即每列的列数一般与NR连用
FILENAME正在处理的文件名,一般与NR连用
awk命令中的逻辑运算符说明
>大于
<小于
>=大于等于
<=小于等于
==等于
!=不等于
+
+=加等于
-
-=减等于
*
*=乘等于
/
/=除等于
%取余
%=取余等于
**或^幂次方
**=或^=幂次方等于
&&且(同java语言中的条件一样)
||或(同java语言中的条件一样)
!逻辑非

内置变量$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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com

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 http://www.girl.com
 
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
qq


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 http://www.girl.com
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 http://www.girl.com
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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值