Linux学习笔记(8)-正则表达式

正则表达式

一、基础正则表达式

正则表达式和通配符的区别:

  • 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配. grep、awk、sed等命令可以支持正则表达式。
  • 通配符( ?[])是用来匹配符合条件的文件名*,通配符是完全匹配。ls、find、cp等命令不支持正则表达式,所有只能使用shell自己的通配符来进行匹配了。
元字符作用
*前一个字符匹配0次或者任意多次
.匹配除了换行符外任意一个字符
^匹配行首,例如:^hello会匹配以hello开头的行。
$匹配行首,例如:hello$会匹配以hello开头的行。
[ ]匹配括号中指定的任意一个字符,只匹配一个字符
[ ^]匹配除中括号的字符意外的任意一个字符。例如:[^0-9]匹配任意一个非数字字符。
\转义符。用于将特殊符号的含义取消
{n}表示其前面的字符签好出现n次。例如:[0-9]{4}匹配4位数字,[1][3-8][0-9]{9} 匹配手机号码
{n,}表示七千亩的字符出现不小于n次。例如:[0-9]{2,}表示两位及以上的数字
{n,m}表示其前面的字符至少出现n次,最多出现m次。例如:[a-z]{6,8}匹配6到8为的小写子母。

范例:

grep "a*" test_rule.txt
#匹配所有内容,包括空白行
grep "aaaa*" test_rule.txt
#匹配最少包含三个连续a的字符串
grep "s..d" test_rule.txt
#匹配在s和d两个子母之间的有两个字符的单词
grep "s.*d" test_rule.txt
#匹配在s和d之间有任意字符的单词所在的行
grep "^M" test_rule.txt
#匹配以大写子母M开头的行
grep "n$" test_rule.txt
#匹配以小写n结尾的行
grep -n "^$" test_rule.txt
#匹配空白行
grep "^[a-z]" test_rule.txt
#匹配以小写子母开头的行
grep "\.$" test_rule.txt
#匹配以.结尾的行

二、字符截取命令

2.1 列截取命令 cut

语法:

cut [选项] [文件名]
      -f 指定选取的列,多列以“,”隔开
      -d 指定分隔符

**局限:**不能很好截取以多个空格作为分隔符的行。


[root@mysql sh]# cat student.txt 
ID      Name    Gender  Score
1       liming  M       88
2       liuwei  M       66
#提取第二、三列数据
[root@mysql sh]# cut -f 2,3 student.txt 
Name    Gender
liming  M
liuwei  M
#指定分隔符为“:”
[root@mysql sh]# cut -d ":" -f 2,3 /etc/passwd
x:0
x:1
x:2
x:3
x:4

2.2 格式化打印命令printf

语法:

printf  '输出类型输出格式' 输出内容
         %ns: 输出字符串。n是数字指代输出几个字符
         %ni: 输出整数。n是数字指代输出几个数字
         %m.nf:输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表输出8位数,其中2位是小数,6位是整数。    

常用输出格式:

\n: 换行
\r: 回车
\t:水平输出退格键,也就是Tab键

范例:

 [root@mysql sh]# printf '%s %s %s\n' 1 2 3 4 5 6
1 2 3
4 5 6

2.3 字符截取命令 awk

语法:

awk '条件1 {动作1} 条件2 {动作2} ……' 文件名
  • 条件(Pattern):
    一般使用关系表达式作为条件
    - x>10 判断变量x是否大于10
    - x>=10 大于等于
    - x<= 小于等于

  • 动作(Action)

    • 格式化输出
    • 流程控制语句

范例:
以多个空格为分隔符的列表

[root@mysql ~]# df -h
Filesystem             Size  Used Avail Use% Mounted on
/dev/mapper/rhel-root   28G  4.3G   24G  16% /
devtmpfs               979M     0  979M   0% /dev
tmpfs                  991M     0  991M   0% /dev/shm
tmpfs                  991M  9.5M  981M   1% /run
tmpfs                  991M     0  991M   0% /sys/fs/cgroup
/dev/sda1              497M  126M  372M  26% /boot
tmpfs                  199M     0  199M   0% /run/user/0

awk 命令中“printf”命令不会自动换行,“print”命令可以自动换行。

[root@mysql ~]# df -h | awk '{printf $1 "\t" $5  "\t" $6  "\t\n"}'
Filesystem      Use%    Mounted
/dev/mapper/rhel-root   16%     /
devtmpfs        0%      /dev
tmpfs   0%      /dev/shm
tmpfs   1%      /run
tmpfs   0%      /sys/fs/cgroup
/dev/sda1       26%     /boot
tmpfs   0%      /run/user/0
[root@mysql ~]# df -h | awk '{print $1 "\t" $3}'
Filesystem      Used
/dev/mapper/rhel-root   4.3G
devtmpfs        0
tmpfs   0
tmpfs   9.6M
tmpfs   0
/dev/sda1       126M
tmpfs   0
[root@mysql ~]# df -h |grep sda1
/dev/sda1              497M  126M  372M  26% /boot
[root@mysql ~]# df -h |grep sda1 | awk '{printf $5}'
26%[root@mysql ~]# df -h |grep sda1 | awk '{printf $5 "\n"}'
26%
[root@mysql ~]# df -h |grep sda1 | awk '{printf $5 "\n"}' | cut -d "%" -f 1
26

BEGIN 命令:先执行期望打印内容之前的命令。

[root@mysql sh]# awk 'BEGIN {print "test!"} {print $2 "\t" $3}' student.txt
test!
Name    Gender
liming  M
liuwei  M

FS内置变量
awk命令默认分割符为“空格”以及“制表符”,无法自动识别“:”

[root@mysql sh]# awk '{print $1 "\t" $3}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

awk 命令会先读取后处理,因此第一行数据没有分割

[root@mysql sh]# awk '{FS=":"} {print $1 "\t" $3}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin     1
daemon  2

添加BEGIN命令强制先处理

[root@mysql sh]# awk 'BEGIN{FS=":"} {print $1 "\t" $3}' /etc/passwd
root    0
bin     1
daemon  2
adm     3
lp      4
sync    5

END命令

[root@mysql sh]# awk 'END{print "The end"} {print $2 "\t" $3}' student.txt student.txt
Name    Gender
liming  M
liuwei  M

The end

关系运算符 :每行的数据先判断才会执行打印命令

[root@mysql sh]# cat student.txt |grep -v Name | awk '$4>=85 {print $2}'
liming

2.4 sed命令

sed是一种几乎包括在所以UNIX平台的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
语法:

[root@localhost ~]# sed [选项] '[动作]' 文件名
 选项:
                          -n	一般sed命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过Sed命令处理的行输出到屏幕。
                          -e:	允许对输入数据应用多条sed命令编辑
                          -i:	用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
							     a \:	(append)追加,在当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾用“\”代表数据未完结。
							     c \:	(change)行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。
							     i \:	(insert)插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用“\”代表数据未完结
							     d:		(delete)删除,删除指定的行
							     p:		(print)打印,输出指定的行
							     s:	(substitute)字串替换。用一个字符串替换另外一个字符串。格式为“行范围s/旧字符/新字符/g” (和vim中的替换格式类似)

范例:
不加“-n“的话,除了输出第二行,所有数据都会输出一遍

[root@mysql sh]# sed '2p' student.txt 
ID      Name    Gender  Score
1       liming  M       88
1       liming  M       88
2       liuwei  M       66

[root@mysql sh]# sed -n '2p' student.txt 
1       liming  M       88

sed命令可以对命令输出结果直接进行处理,vi命令只能处理文件

[root@mysql sh]# df -h | sed -n '2p' 
/dev/mapper/rhel-root   28G  4.3G   24G  16% /

删除行,没有修改文件本身的内容,只是对输出进行了处理

[root@mysql sh]# sed '2,3d' student.txt 
ID      Name    Gender  Score
3       zhao    M       90

插入行

[root@mysql sh]# sed '4i hello' student.txt 
ID      Name    Gender  Score
1       liming  M       88
2       liuwei  M       66
hello
3       zhao    M       90
[root@mysql sh]# sed '3a hello \ world' student.txt   #”\“表示没输入完
ID      Name    Gender  Score
1       liming  M       88
2       liuwei  M       66
hello  world
3       zhao    M       90

行替换

[root@mysql sh]# sed '4c no such person' student.txt 
ID      Name    Gender  Score
1       liming  M       88
2       liuwei  M       66
no such person

字符串替换

[root@mysql sh]# sed '4s/90/95/g' student.txt 
ID      Name    Gender  Score
1       liming  M       88
2       liuwei  M       66
3       zhao    M       95

三、字符处理命令

3.1排序命令 sort

格式:

[root@localhost ~]# sort [选项] 文件名
						  -f	忽略大小写
						  -n	以数值型进行排序,默认使用字符串型排序
						  -r	反向排序
						  -t	指定分隔符,默认是分隔符是制表符
						  -k n[,m]:	按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)

范例:
根据用户的”uid“(第三个字段)进行排序

[root@mysql sh]# sort -n -t ":" -k 3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync

3.2 统计命令 wc

格式:

[root@localhost ~]# wc [选项] 文件名
                         -l:	只统计行数
                         -w:	只统计单词数
                         -m:	只统计字符数

范例:

[root@mysql sh]# wc /etc/passwd
 20  28 876 /etc/passwd
 # 20行 28个单词 876个字符

四、条件判断

4.1 根据文件类型进行判断

测试一个条件是否成立,常用的选项有三个

测试选项作用
-b 文件判断该文件受否存在,并且是否为块设备文件(是块设备文件为真)
-c 文件判断该文件受否存在,并且是否为字符设备文件(是字符设备文件为真)
-d 文件判断该文件受否存在,并且是否为目录文件(是目录文件为真)
-e 文件判断该文件受否存在(存在为真)
-f 文件判断该文件受否存在,并且是否为普通文件(是普通文件为真)
-L 文件判断该文件受否存在,并且是否为符号链接文件(是符号链接文件为真)
-p 文件判断该文件受否存在,并且是否为管道文件(是管道文件为真)
-s 文件判断该文件受否存在,并且是否为非空(非空为真)
-S 文件判断该文件受否存在,并且是否为套接字(是套接字文件为真)

两只判别格式范例:

[root@mysql sh]# test -e student.txt
[root@mysql sh]# echo $?   #查看上一条命令是否执行正确
0
[root@mysql sh]# [ -e student.txt ]
[root@mysql sh]# echo $?
0
#第一条判断命令如果正确执行,打印”yes",否则打印”no“
[root@mysql sh]# [ -e studnt.txt ] && echo "Yes" ||echo "No"
No
[root@mysql sh]# [ -e student.txt ] && echo "Yes"||echo "No"
Yes

4.2按照文件权限进行判断

测试选项作用
-r 文件判断该文件受否存在,并且是否该文件有读权限(有读权限为真)
-w 文件判断该文件受否存在,并且是否该文件有写权限(有写权限为真)
-x 文件判断该文件受否存在,并且是否该文件执行权限(有执行权限为真)
-u 文件判断该文件受否存在,并且是否该文件有SUID权限(有SUID权限为真)
-g 文件判断该文件受否存在,并且是否该文件有SGID权限(有SGID权限为真)
-k 文件判断该文件受否存在,并且是否该文件有SBit权限(有SBit权限为真)

范例:

[root@mysql sh]# [ -w student.txt ] && echo "yes" ||echo "no"
yes

4.3两个文件进行比较判断

测试选项作用
文件1 -nt 文件2判断文件1的修改时间是否比文件2的新(如果新则为真)newer than
文件1 -ot 文件2判断文件1的修改时间是否比文件2的旧(如果旧则为真) older than
文件1 -ef 文件2判断文件1是否和文件2的Inode号(i节点)一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接 equal file

范例:

ln /tmp/sh/student.txt /tmp/stu.txt  #创建硬链接
[root@mysql sh]# [ /tmp/stu.txt -ef /tmp/sh/student.txt ] && echo "yes" || echo "no"
yes
[root@mysql sh]# ls -i /tmp/stu.txt #查看文件i节点
17187280 /tmp/stu.txt
[root@mysql sh]# ls -i /tmp/sh/student.txt
17187280 /tmp/sh/student.txt

4.4 两个整数进行比较

测试选项作用
整数1 -eq 整数2判断整数1是否和整数2相等(相等为真)equal
整数1 -ne 整数2判断整数1是否和整数2不相等(不相等为真)not equal
文件1 -gt 文件2判断整数1是否大于整数2(大于为真)
文件1 -lt 文件2判断整数1是否小于整数2(小于为真)
文件1 -ge 文件2判断整数1是否大于等于整数2(大于等于为真)
文件1 -le 文件2判断整数1是否小于等于整数2(小于等于为真)

范例:

[root@mysql sh]# [ 23 -le 30 ] && echo "yes" || echo "no"
yes

4.5 字符串的判断

测试选项作用
-e 字符串判断字符串是否为空(为空返回真)
-n 字符串判断字符串是否为非空(非空返回真)
字符串1 == 字符串2判断字符串1是否和字符串2相等(相等返回真)
字符串1 != 字符串2判断字符串1是否和字符串2不相等(不相等返回真)

范例:

[root@mysql sh]# [ -z "$name" ] && echo "yes" || echo "no"
no
[root@mysql sh]# [ "$aa" == "$bb" ] && echo "yes" || echo "no" ##”==“两边要加空格否则全判断为真
no  

4.6 多重条件判断

测试选项作用
判断1 -a 判断2逻辑与,判断1和判断2都成立,最终的结果才为真
判断1 -o 判断2逻辑或,判断1和判断2有一个成立,最终的结果才为真
! 判断逻辑非,使原始的判断式取反

五、流程控制

5.1 if语句

单分支if 语句格式:

if [ 条件判断式 ] ; then
	程序
fi 

或者

if [条件判断式]
	then
		程序
fi

判断分区使用率范例:

#脚本内容
[root@mysql ~]# more /tmp/sh/if_test.sh
#!/bin/bash
#统计根分区使用率

rate=$(df -h | grep "/dev/sda1" | awk '{print $5}' | cut -d "%" -f1)
#把根分区使用率作为变量值赋给rete

if [ $rate -le 80 ]
        then
                echo "$rate"  "Warning /dev/sda3 isn't full!!"
#脚本运行结果
[root@mysql ~]# /tmp/sh/if_test.sh
26 Warning /dev/sda3 isn't full!!

双分支if语句格式:

if [ 条件判断式 ]
	then
		条件成立时,执行的程序
	else
		条件不成立时,执行的另一个程序
fi

备份范例:

[root@mysql sh]# cat -n if_test2.sh
     1  #!/bin/bash
     2
     3  date=$(date +%y%m%d)
     4  size=$(du -sh /tmp)
     5
     6  if [ -d /tmp/dbback ]
     7          then
     8                  echo "Date is : $date" > /tmp/dbback/db.txt
     9                  echo "Size is : $size" >> /tmp/dbback/db.txt
    10                  tar -zcf tmp_$date.tar.gz /tmp &> /dev/null
    11                  rm -rf /tmp/dbback/db.txt
    12          else
    13                  madir /tmp/dbback
    14
    15                  echo "Date is : $date" > /tmp/dbback/db.txt
    16                  echo "Size is : $size" >> /tmp/dbback/db.txt
    17                  tar -zcf tmp_$date.tar.gz /tmp &> /dev/null
    18                  rm -rf /tmp/dbback/db.txt
    19  fi

范例2 :判断apache是否启动

[root@mysql sh]# more if_test3.sh
#!/bin/bash

port=$(nmap -sT 192.168.160.10 | grep tcp | grep httpd | awk '{print $2}')
#使用nmap命令扫描服务器并截取apache状态,赋值给变量port

if [ "$port" == "open" ]
        then 
                echo "$(date) httpd is ok!" >> /tmp/autostart_acc.log
        else
                /etc/rc.d/init.d/httpd_start &> /dev/null
                echo "$(date) restart httpd!!" >> /tmp/autostart_acc.log
fi

多分支if语句格式:

if [ 条件判断式1 ]
	then
		当条件判断式1成立时,执行程序1
elif [ 条件判断式2 ]
	then
		当条件判断式2成立时,执行程序2
	……省略更多条件
else
		当所有条件都不成立时,最后执行此程序
fi	

文件类型判断范例:

[root@mysql sh]# cat -n if_test4.sh
     1  #!/bin/bash
     2
     3  read -p "Please input a filename :" file
     4  #接收键盘的输入,并赋值给file
     5
     6  if [ -z "$file"]
     7          #判断file是否为空
     8          then
     9                  echo "Erro please input a filename"
    10                  exit 1
    11  elif [ ! -e "$file" ]
    12  #判断file的值是否存在
    13          then
    14                  echo "Your put is not a file"
    15                  exit 2
    16  elif [ -f "$file" ]
    17  #判断file的值是否为普通文件
    18          then
    19                  echo "file is a regulare file"
    20  elif [ -d "$file" ]
    21  #判断file是否为目录文件
    22          then
    23                  echo "file is a directory"
    24  else
    25                  echo "file is another file!"
    26  fi

5.2 case语句

case语句只能匹配一种条件语句,if语句可以匹配多种条件语句。
格式:

case $变量名 in
	"值1")
		如果变量的值等于值1,则执行程序1
		;;
	"值2")
		如果变量的值等于值2,则执行程序2
		;;
	*)
		如果变量的值都不是以上的值,则执行此程序
		;;
esac

范例:

[root@mysql sh]# cat -n /tmp/sh/case.sh
     1  #!/bin/bash
     2
     3
     4  read -p "Please choose yes/no " -t 30 cho
     5  case $cho in
     6          "yes")
     7                  echo "your choice is yes!"
     8                  ;;
     9          "no")
    10                  echo "your choice is no!"
    11                  ;;
    12          *)
    13                  echo "your choice is error!"
    14                  ;;
    15  esac

5.3 for 循环

语法1:

for 变量 in 值1 值2 值3……
	do
		程序
	done

范例:

[root@mysql sh]# cat -n /tmp/sh/for2.sh
     1  #!/bin/bash
     2  #批量解压缩脚本
     3
     4  cd /lamp
     5  ls *.tar.gz > ls.log
     6  for i in $(cat ls.log)
     7          do
     8                  tar -zxf $i &> /dev/null
     9          done
    10  rm -rf /lamp/ls.log

语法2:

for ((初始值;循环控制变量;变量变化))
	do
		程序
	done

范例:

[root@mysql sh]# cat -n /tmp/sh/for3.sh
     1  #!/bin/bash
     2  #计算从1加到100
     3
     4  s=0
     5  for ((i=1;i<=100;i=i+1))
     6          do
     7                  s=$(( $s+$i ))
     8          done
     9  echo "The sum of 1+2+3+…… is: $s"
[root@mysql sh]# cat -n /tmp/sh/for4.sh
     1  #!/bin/bash
     2  #批量添加用户
     3
     4  read -p "Please input the username:" name
     5
     6  read -p "Please input the number of  users:" num
     7
     8  read -p "Please input the password of users:" pass
     9  if [ ! -z "$name" -a ! -z "$num" -a ! -z "$pass" ]
    10  #判断三个输入是否都不为空
    11          then
    12                  y=$(echo $num | sed 's/^[0-9]*$'//g)
    13                  #将以数字开头以任意字符结尾的num替换为空
    14                  if [ -z "$y" ]
    15                          then
    16                                  for ((i=1;i<=num;i=i+1))
    17                                          do
    18                                                  /usr/sbin/useradd $name$i &> /dev/null
    19                                                  echo $pass | usr/bin/passwd --stdin “$name$i” &>/dev/null
    20                                                  #stdin重定向输入,管道符接收前面指令结果作为后面指令的输入
    21                                          done
    22                  fi
    23  fi

5.4 while循环与until循环

while 循环时不定循环,也称作条件循环。只要条件判断式成立,循环就会一直继续,直到条件判断式不成立,循环才会停止。这就和for的固定循环不太一样了。
语法:

while [ 条件判别式 ]
	do
		程序
	done

范例:

[root@mysql sh]# cat -n /tmp/sh/while.sh
     1  #!/bin/bash
     2  #计算1到100的和
     3
     4  s=o
     5  i=1
     6  while [ $i -le 100 ]
     7          do
     8                  s=$(( $s+$i ))
     9                  i=$(( $i+1 ))
    10          done
    11  echo "The sum is : $s"

until 循环,和while循环相反,until循环时只要条件判断式不成立则进行循环,并执行循环程序。一旦循环条件成立,则终止循环。
范例:

[root@mysql sh]# cat -n /tmp/sh/until.sh
     1  #!/bin/bash
     2
     3  s=0
     4  i=1
     5  until [ $i -gt 100 ]
     6  #循环直到变量i的值大于100
     7          do
     8                  s=$(( $s+$i ))
     9                  i=$(( $i+1 ))
    10          done
    11  echo "The sum is :$s"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值