Linux第十一章 shell编程

第十一章 shell编程

正则表达式

正则表达式与通配符

  • 区别 :

正则表达式是在文件中匹配字符串的, grep, awk, sed等命令可以支持正则表达式, 它是包含匹配.

通配符是匹配文件名的, ls, find, cp等命令不支持正则表达式, 只能使用通配符来匹配, 它是完全匹配.

他们的区别只限于linux系统, 其他编程语言不受限.

基础正则表达式

  • 配合grep命令使用
元字符作用
*前一个字符匹配0次或多次
.匹配任意一个字符 ( 除了换行符 )
^匹配行首, 如^hello会匹配以hello开头的行
$匹配行尾
[]匹配括号中指定的任意一个字符
[^]匹配非括号中的
\转义符
\{n\}前面的字符恰好出现n次, 如[0-9]\{4\}匹配数字出现4个的行
\{n,\}前面的字符出现不小于n次
\{n,m\}前面的字符至少出现n次, 最多出现m次

如:

[root@localhost tmp]# grep "c\{1,4\}" test
cccc123
cccc

字符截取命令

  • cut
    cut [参数] 文件名 : 匹配符合条件的列
    参数 :
    -f 列号 : 提取第几列
    -d 分隔符 : 按照指定分隔符割列

局限性 : cut命令的默认分隔符为tab键, 如果匹配以空格为分隔符的内容, 则需使用awk命令.

[root@localhost tmp]# cat student
name    age     gender  id
a       20      m       1
b       21      f       2
c       20      f       3
d       19      m       4
[root@localhost tmp]# cut -f 1,4 student
name    id
a       1
b       2
c       3
d       4
[root@localhost tmp]# cat /etc/passwd		#查看/etc/passwd文件
{
	root:x:0:0:root:/root:/bin/bash
	省略
	ntp:x:38:38::/etc/ntp:/sbin/nologin
	tcpdump:x:72:72::/:/sbin/nologin
	apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
	centos:x:1000:1000::/home/centos:/bin/bash
}
[root@localhost tmp]# cat /etc/passwd | grep "/bin/bash$" 		#查看可登录的用户及信息
{
	root:x:0:0:root:/root:/bin/bash
	centos:x:1000:1000::/home/centos:/bin/bash
}
[root@localhost tmp]# cat /etc/passwd | grep "/bin/bash$" | grep -v "^root"		#查看除了root用户的信息
{
	centos:x:1000:1000::/home/centos:/bin/bash
}
[root@localhost tmp]# cat /etc/passwd | grep "/bin/bash$" | grep -v "^root" | cut -d ":" -f "1,3"		#查看其他用户的第1和3列信息
{
	centos:1000
}
  • printf
    printf '输出类型输出格式' 输出内容
    • 输出类型 :
      • %s : 输出字符串
      • %i : 输出整数
      • %m.nf : 输出浮点数, m-n是整数位, n是小数位
    • 输出格式 :
      • \n : 换行
      • \r : 回车
      • \t : tab键
[root@localhost tmp]# printf '%s\n' 1 2 3
1
2
3
[root@localhost tmp]# printf '%s %s %s\n' 1 2 3 4 5 6
1 2 3
4 5 6
[root@localhost tmp]# printf '%s\t %s\t %s\t %s\n' $(cat student)
name     age     gender  id
a        20      m       1
b        21      f       2
c        20      f       3
d        19      m       4
[root@localhost tmp]# cat student
name    age     gender  id
a       20      m       1
b       21      f       2
c       20      f       3
d       19      m       4
  • awk

awk命令是截取列的, 当cut命令无法实现功能时, 使用awk命令.

awk '条件1 {动作1} 条件2 {动作2} ...' 文件名

[root@localhost tmp]# awk '{printf $1 "\t" $2 "\n"}' test.student 		# $1表示提取第一列
name    id		#条件为任意
a       1
b       2
c       3
d       4
[root@localhost tmp]# df -h | awk '{printf $1 "\t" $5 "\t" $6 "\n"}' 
Filesystem      Use%    Mounted		# 解决cut命令的缺陷
devtmpfs        0%      /dev
tmpfs   0%      /dev/shm
tmpfs   2%      /run
tmpfs   0%      /sys/fs/cgroup
/dev/mapper/centos-root 56%     /
/dev/sda1       83%     /boot
tmpfs   1%      /run/user/42
tmpfs   0%      /run/user/0

BEGIN 动作 : 条件, 在最开始的时候执行这个动作
END 动作 : 条件, 在最后的时候执行这个动作
FS="分隔符" : 指定分隔符, awk中默认分隔符为空格或制表符

[root@localhost tmp]# awk 'BEGIN{FS=":"} {printf $1 "\t" $3 "\n"} END{printf "ok" "\n"}' /etc/passwd 
root    0
省略
centos  1000
ok

关系运算符 : 条件, 符合条件的才匹配

[root@localhost tmp]# cat test.student
name    id      gender  age
a       1       m       10
b       2       m       11
c       3       f       10
d       4       f       11
[root@localhost tmp]# awk '$4>10 {printf $1 "\t" $4 "\n"}' test.student 
name    age
b       11
d       11
  • sed

是一种流编辑器, 它与vi的区别在于, 它可以编辑管道符后面的内容.

sed [参数] '动作' 文件名
参数:
-n : 不再显示全部内容, 而是显示具体的操作的内容, 与动作p一块使用
-e : 使多个动作同时进行
-i : 会直接修改文件 ( 其他都不会修改文件内容 )
动作:
p : 打印指定的行
d : 删除指定的行
a : 追加, 在行的下面
c : 行替换
s/旧/新/g : 字符串替换
i : 插入, 在行的上面

[root@localhost tmp]# cat test.student 
name    id      gender  age
a       1       m       10
b       2       m       11
c       3       f       10
d       4       f       11
[root@localhost tmp]# sed -n '2p' test.student 
a       1       m       10
[root@localhost tmp]# sed '2a curry' test.student 
name    id      gender  age
a       1       m       10
curry
b       2       m       11
c       3       f       10
d       4       f       11
[root@localhost tmp]# sed '3i cu' test.student 
name    id      gender  age
a       1       m       10
cu
b       2       m       11
c       3       f       10
d       4       f       11
[root@localhost tmp]# sed '3d' test.student 
name    id      gender  age
a       1       m       10
c       3       f       10
d       4       f       11
[root@localhost tmp]# sed '3c curry' test.student 
name    id      gender  age
a       1       m       10
curry
c       3       f       10
d       4       f       11
[root@localhost tmp]# sed 's/name/n/g' test.student 
n       id      gender  age
a       1       m       10
b       2       m       11
c       3       f       10
d       4       f       11
[root@localhost tmp]# sed -e 's/name/n/g ; s/age/a/g' test.student 
n       id      gender  a
a       1       m       10
b       2       m       11
c       3       f       10
d       4       f       11

字符处理命令

sort命令

  • sort [参数] 文件名 : 排序
    • 参数 :
      • -f : 忽略大小写
      • -r : 反向排序
      • -t : 指定分隔符, 默认为制表符
      • -k 3 : 对第三列进行排序
[root@localhost tmp]# sort test.student 
a       1       m       10
b       2       m       11
c       3       f       10
d       4       f       11
name    id      gender  age
[root@localhost tmp]# sort -r test.student 
name    id      gender  age
d       4       f       11
c       3       f       10
b       2       m       11
a       1       m       10
[root@localhost tmp]# cat test.student 
name    id      gender  age
a       1       m       10
b       2       m       11
c       3       f       10
d       4       f       11

wc命令

  • wc [参数] 文件名 : 统计
    • 参数 :
      • -l : 只统计行数
      • -w : 单词数
      • -m : 字符数
[root@localhost tmp]# wc test.student 
 5 20 55 test.student
[root@localhost tmp]# wc -l test.student 
5 test.student
[root@localhost tmp]# wc -w test.student 
20 test.student
[root@localhost tmp]# wc -m test.student 
55 test.student

条件判断

  • 按照文件类型进行判断
    -d 文件 : 判断文件是否存在, 并且是否为目录文件 ( 是目录为真 )
    -e 文件 : 判断文件是否存在 ( 存在为真 )
    -f 文件 : 判断文件是否存在, 并且是否为普通文件 ( 是普通文件为真 )
    • 判断格式:
      [ -e 文件 ]
    [root@localhost tmp]# [ -e test.student ] && echo "yes" || echo "no"
    yes
    
  • 按照文件权限进行判断
    -r 文件 : 判断文件是否存在, 并且是否文件拥有读权限 ( 有读权限为真 )
    -w 文件 : 判断文件是否存在, 并且是否文件拥有写权限 ( 有写权限为真 )
    -x 文件 : 判断文件是否存在, 并且是否文件拥有执行权限 ( 有执行权限为真 )
  • 两个文件之间进行比较
    文件1 -nt 文件2 : 判断文件1的修改时间是否比文件2的新 ( 如果新则为真 )
    文件1 -ot 文件2 : 判断文件1的修改时间是否比文件2的旧 ( 如果旧则为真 )
    文件1 -ef 文件2 : 判断文件1是否和文件2的inode号一致 ( 如果一致为真 ), 可以判断硬链接
  • 两个整数之间比较
    整数1 -eq 整数2 : 判断整数1是否和整数2相等
    -ne : 不相等
    -gt : 大于
    -lt : 小于
    -ge : 大于等于
    -le : 小于等于
  • 字符串的判断
    -z 字符串 : 判断字符串是否为空
    -n : 非空
    1 == 2 : 相等
    1 != 2 : 不相等
  • 多重条件判断
    判断1 -a 判断2 : 逻辑与, 都成立为真
    1 -o 2 : 逻辑或, 有一个成立就为真
    ! 判断 : 逻辑非, 使判断式取反

流程控制

if

  • 单分支
if [ 条件判断 ]
	then
		执行语句
fi
[root@localhost tmp]#  cat if1.sh 
#!/bin/bash

rate=$(df -h | grep "/dev/sda1" | awk '{printf $5 "\n"}' | cut -d "%" -f 1)

if [ $rate -ge 80 ]
        then
                echo "waring : /dev/sda1 is full!"
fi
  • 多分支
if [ 条件判断1 ]
	then
		执行语句1	# 条件1成立时, 执行
	else
elif [ 条件判断2 ]
	then
		执行语句2	# 条件2成立时, 执行
else
		执行语句3	# 当所有条件都不成立时, 执行
fi
[root@localhost tmp]# cat if2.sh 
#!/bin/bash

read -p "please input a filename :" file

if [ -z $file ]
        then
                echo "it is null"
        exit 0
elif [ ! -e $file ]
        then
                echo "it is unlive"
        exit 1
elif [ -d $file ]
        then
                echo "it is a directory"
elif [ -f $file ]
        then
                echo "it is a file"
fi
[root@localhost tmp]# ./if2.sh 
please input a filename :
it is null
[root@localhost tmp]# ./if2.sh 
please input a filename :asd
it is unlive
[root@localhost tmp]# ./if2.sh 
please input a filename :test
it is a file
[root@localhost tmp]# ./if2.sh 
please input a filename :/tmp
it is a directory

case

  • case语句只能判断一种条件关系, 而if语句可以判断多种条件关系.
  • 格式 :
case $变量 in
	"值1")
		语句1 ( 如果变量的值为1, 则执行 )
		;;
	"值2")
		语句2
		;;
	...等
	*)
		语句 ( 如果变量的值都不是以上的值, 则执行 )
		;;
esac
[root@localhost tmp]# cat case3.sh 
#!/bin/bash

read -p "please input a day : " day

case $day in
        [1-5])
                echo "workday"
                ;;
        [6-7])
                echo "weekday"
                ;;
        *)
                echo "error"
                ;;
esac
[root@localhost tmp]# ./case3.sh 
please input a day : 2
workday
[root@localhost tmp]# ./case3.sh 
please input a day : 4
workday
[root@localhost tmp]# ./case3.sh 
please input a day : 7
weekday
[root@localhost tmp]# ./case3.sh 
please input a day : 10
error

for

  • 循环
  • 格式1 :
for 变量 in 值1 值2 值3 ...等
	do
		语句
	done
[root@localhost tmp]# vi for1.sh 
      1 #!/bin/bash
      2 
      3 cd /tmp
      4 
      5 ls *.sh > sh
      6 
      7 j=1
      8 
      9 for i in $(cat sh)
     10         do
     11                 echo $j
     12                 j=$(( j+=1 ))
     13         done
~
~
~
~
~
~
"for1.sh" 13L, 96C written
[root@localhost tmp]# ./for1.sh 
1
2
3
4
5
6
7
8
9
10
11
12		# 一共12个shell脚本
  • 格式2 :
for (( 初始值; 循环控制条件; 变量变换 ))
	do
		语句
	done
[root@localhost tmp]# cat for2.sh 
#!/bin/bash

i=1

for ((i=1; i<=10 ;i+=1))
        do
                echo $i
        done
[root@localhost tmp]# ./for2.sh 
1
2
3
4
5
6
7
8
9
10
[root@localhost tmp]# vi for3.sh
      1 #!/bin/bash
      2 
      3 sum=0
      4 
      5 for ((i=1;i<=100;i+=1))
      6         do
      7                 sum=$(($sum+$i))
      8         done
      9 
     10 echo $sum
"for3.sh" 10L, 84C written
[root@localhost tmp]# ./for3.sh 
5050

while

  • while循环只要判断条件成立, 循环就会一直继续 ( 可以无限循环 )
  • 格式
while [ 条件判断 ]
	do
		语句
	done
[root@localhost tmp]# cat while1.sh 
#!/bin/bash

i=1
sum=0

while [ $i -le 100 ]
        do
                sum=$(($sum+$i))
                i=$(($i+1))
        done
echo "sum=$sum"
[root@localhost tmp]# ./while1.sh 
sum=5050
[root@localhost tmp]# cat while2.sh 
#!/bin/bash

sum1=0
sum2=0
i=0

while [ $i -le 100 ]
        do
                if [ $(($i % 2)) != 0 ]
                        then
                                sum1=$(($sum1+$i))
                fi

                if [ $(($i % 2)) == 0 ]
                        then
                                sum2=$(($sum2+$i))
                fi
                i=$(($i+1))
        done
echo "sum1=$sum1"
echo "sum2=$sum2"
[root@localhost tmp]# ./while2.sh 
sum1=2500
sum2=2550
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值