回顾:重定向、管道、算术运算、位置参数、特殊变量、交互式脚本



文本处理工具之grep、egrep和fgrep:


grep: (global search regular expression(RE) and print out the line


文本搜索工具,根据用户指定的文本模式对目标文件进行逐行搜索,显示能够被模式所匹配到的行


格式:grep [options] 'PATTERN'(正则表达式) file,... 显示匹配字符串的那一行

--color=auto 可以使找到的匹配串变颜色


正则表达式:是一类字符所书写出的模式(pattern),在指定文件中找指定匹配

元字符:不表示字符本身的意义,用于额外功能性的描述


基本正则表达式和扩展正则表达式


前面使用的是文件通配符,和这个一点都不一样,注意区分

基本正则表式的元字符:grep -E

字符匹配:

.: 任意单个字符

[]: 指定范围内的任意单个字符

[0-9], [[:digit:]]

[a-z], [[:lower:]]

[A-Z], [[:upper:]]

[[:alpha:]]

[[:alnum:]]

[[:space:]]

[[:punct:]]

[^]:指定范围外的任意单个字符

次数匹配:用来指定匹配其前面的字符的次数

*: 任意次

例子:x*y, xxy, xy, y,    表示x可以出现任意次,0或多次

.*: 匹配任意长度的任意字符

\?: 0次或1次

x\?y, xy, y, xxy(后面的xy可以)


贪婪模式:尽可能的长的去匹配字符;

\{m\}: 匹配m次

\{m,n\}:

\{m,\}: 至少m次;

\{0,n\}:至多n次;


[root@zhenzhen ~]# grep 'x\{4,\}y' shell5.sh 

xxxxxy

xxxxxxxxxxxxxxxxxxxxxy

[root@zhenzhen ~]# grep --color=auto '[Rr][^[:punct:]]*[Tt]' /etc/passwd  这里^是非的意思


位置锚定:用于指定字符出现的位置,指定行的

^: 锚定行首

^Char

[root@zhenzhen ~]# grep --color=auto '^[Rr][^[:punct:]]*[Tt]' /etc/passwd  

前面的^是行首指定是什么,中间的^是非

$: 锚定行尾

char$

^$: 空白行

[root@zhenzhen ~]# grep '^$' /etc/rc.d/rc.sysinit | wc -l

96


词锚定是指符号之间的

\<char: 锚定词首,\bchar

char\>: 锚定词尾,char\b

锚定的作用\< \> 是用来找出两个符号之间的单词,对该单词合格的则匹配成功!!!!!

分组:

\(\)

\(ab\)*xy

引用:

\1: 后向引用,引用前面的第一个左括号以及与之对应的右括号中的模式所匹配到的内容

\2

...

\(a.b\)xy\1: a6bxya6b,    1一定时匹配的是前面全一样的结果,a6bxya7b就无法匹配成功


He like his lover.

She love her liker.

He love his lover.

She like her liker.


grep 常用选项:

-v: 反向,显示不能被模式所匹配到的行,而匹配的反而不显示

-o: 仅显示被模式匹配到的字串,而非整行;

-i: 不区分字符大小写, ignore-case

-E: 支持扩展的正则表达式

-A #:显示匹配到的行,并且也显示后面的#行  表示after

-B #  before  也显示前面#行

-C #  context  上下个显示#行


练习:

1、显示/proc/meminfo文件中以大小写s开头的行;

# grep "^[sS]" /proc/meminfo

# grep -i "^s" /proc/meminfo

2、取出默认shell为非bash的用户;

# grep -v "bash$" /etc/passwd | cut -d: -f1

3、取出默认shell为bash的且其ID号最大的用户;

# grep "bash$" /etc/passwd | sort -n -t: -k3 | tail -1 | cut -d: -f1

4、显示/etc/rc.d/rc.sysinit文件中,以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行;

# grep "^#[[:space:]]\{1,\}[^[:space:]]\{1,\}" /etc/rc.d/rc.sysinit

5、显示/boot/grub/grub.conf中以至少一个空白字符开头的行;

# grep "^[[:space:]]\{1,\}[^[:space:]]\{1,\}" /boot/grub/grub.conf 

6、找出/etc/passwd文件中一位数或两位数;这里是锚定,如果是几个连续的数字,则不会匹配

# grep --color=auto "\<[0-9]\{1,2\}\>" /etc/passwd

7、找出ifconfig命令结果中的1到255之间的整数;一定要注意分组

# ifconfig | grep -E --color=auto "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"

8、查看当前系统上root用户的所有信息;

# grep "^root\>" /etc/passwd

9、添加用户bash和testbash、basher,而后找出当前系统上其用户名和默认shell相同的用户;

# grep --color=auto "^\([[:alnum:]]\{1,\}\)\>.*\1$" /etc/passwd

10、找出netstat -tan命令执行的结果中以“LISTEN”或“ESTABLISHED”结尾的行;

# netstat -tan | grep -E '(LISTEN|ESTABLISHED)[[:space:]]*$'

11、取出当前系统上所有用户的shell,要求:每种shell只显示一次,且按升序显示;

# cut -d: -f7 /etc/passwd | sort -u

挑战题:写一个模式,能匹配真正意义上的IP地址;(1.0.0.1--223.255.255.254)

[root@zhenzhen ~]# ifconfig | grep -E --color=auto "(\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>.){3}"

这个是匹配了三次的,有缺陷,还有就是每个字段的大小也有限制

锚定的作用\< \> 是用来找出两个符号之间的单词,对该单词合格的则匹配成功


grep, egrep, fgrep

egrep: 使用扩展正则表达来构建模式,相当于grep -E 

元字符:

字符匹配:

.: 任意单个字符

[]: 指定范围内的任意单个字符

[^]: 指定范围外的任意单个字符

次数匹配:

*:匹配其前面的字符任意次;

?: 匹配其前面的字符0或1次;

+: 匹配其前面的字符至少1次

{m}: 匹配其前面的字符m次;

{m,n}: 至少m次,至多n次

{m,}: 至少m次;

{0,n}:至多n次;

锚定:

^: 行首

$: 行尾

\<, \b: 词首

\>, \b:词尾

分组:

(): 分组


|: 或者, ac|bc

grep -E "con(C|c)at" 

conC或cat

conCat或concat





练习:写一个脚本,分别统计/etc/rc.d/rc.sysinit、/etc/init.d/functions和/etc/fstab文件中各自以#开头的行的行数,以及空白行的行数;

#!/bin/bash


for filename in /etc/rc.d/rc.sysinit /etc/init.d/functions /etc/fstab;do

  echo -n "$filename: "

  lines=`grep '^#' $filename | wc -l`

  echo -n "#--$lines"

  lines=`grep '^$' $filename | wc -l`

  echo "space--$lines"

done


练习:写一个脚本,分别复制/etc/rc.d/rc.sysinit、/etc/init.d/functions和/etc/fstab文件至/tmp目录中,文件名为原名后跟上当前的日期组成;

例如第一个文件复制后的名称为/tmp/rc.sysinit-2-14-02-16;

#!/bin/bash


des='/tmp'

for filename in /etc/rc.d/rc.sysinit /etc/init.d/functions /etc/fstab;do

  cp $filename $des

  newfile=${des}/`basename $filename`

  lastfile=${des}/`basename $filename`-`date +%Y-%m-%d`

  mv $newfile $lastfile

done


练习:写一个脚本

显示当前系统上所有默认shell为bash的用户的用户名、UID以及其在/etc/passwd文件中的行号;

#!/bin/bash

declare -i sumLine=0

sumLine=`wc -l /etc/passwd | cut -d' ' -f1`

for line in `seq 1 $sumLine`;do

  touch /tmp/middle

  user=`head -n${line} /etc/passwd | tail -1 | grep '/bin/bash$' | cut -d: -f1,3`

  echo "$line $user" >> /tmp/middle

done

grep '^[[:digit:]]* [^[:space:]]' /tmp/middle


第一篇博客:讲清楚grep和egrep的使用


fgrep: fast, 不解析正则表达式




bash编程之条件判断:判定后续操作的前提条件是否满足。



mkdir /tmp/scripttest


条件判断的常用测试类型:

整数测试

字符测试

文件测试


$?:

0

1-255


布尔值:

真,假

逻辑运算:

与运算:

真 && 真 = 真

真 && 假 = 假

假 && 真 = 假

假 && 假 = 假

或运算:

真 || 真 = 真

真 || 假 = 真

假 || 真 = 真

假 || 假 = 假

非运算:

! 真 = 假

! 假 = 真


bash中如何做测试:

test EXPRESSION

[ EXPRESSION ]

` EXPRESSION `


bash中条件判断使用if:

单分支:

if 条件; then

分支1; 

fi


双分支:

if 条件; then

分支1;

else

分支2;

fi


多分支:

if 条件1; then

分支1;

elif 条件2; then

分支2;

elif 条件3; then

分支3;

...

else

分支n;

fi


练习:让用指定一个文件,判定:

如果文件有空白行,就显示空白行数;

#!/bin/bash

#

read -p "Enter a file path: " fileName


if grep "^$" $fileName &> /dev/null; then

linesCount=`grep "^$" $fileName | wc -l`

echo "$fileName has $linesCount space lines."

fi


练习:让用指定一个文件,判定:

如果文件有空白行,就显示空白行数;否则,就说明文件无空白行;

#!/bin/bash

#

read -p "Enter a file path: " fileName


if grep "^$" $fileName &> /dev/null; then

       linesCount=`grep "^$" $fileName | wc -l`

       echo "$fileName has $linesCount space lines."

else

    echo "$fileName hava no space line."

fi


grep "^$" $fileName &> /dev/null 这里不需要加``,因为if使用的是该语句的状态结果,如果该语句执行成功,则进入即可



bash编程之:整数测试

二元测试:

num1 OPRAND num2

-gt: 大于[ $num1 -gt $num2 ] 大于则返回真,否则返回假

-lt: 小于

-ge:大于等于

-le: 小于等于

-ne: 不等于

-eq: 等于


练习:判定两个数孰大孰小,整数是通过命令行参数传递而来。


#!/bin/bash

#

if [ $1 -gt $2 ]; then

echo "The max num is $1."

else

echo "The max num is $2."

fi


bash知识点之脚本自定义退出:

exit [n]

使用: exit 8   

1,2,127,255是预留的


练习:判定两个数孰大孰小,整数是通过命令行参数传递而来,如果参数数量传递错误则退出


#!/bin/bash

#

if [ $# -lt 2 ]; then                     $#是引用参数个数

       echo "Stupid..."

       echo "Usage: `basename $0` argu1 argu2"

       exit 4

fi


if [ $1 -gt $2 ]; then

       echo "The max num is $1."

else

    echo "The max num is $2."

fi



grep "^root\>" /etc/passwd

id root



bash知识点:只要命令用作条件,就表示引用是其状态结果(即执行成功与否),而非命令的输出结果,因此,不能使用命令替换符,即``

             引用命令执行结果的话才需要``

             if语句可以识别状态结果,如果命令执行成功,则进入