Linux学习之shell编程

一、正则表达式

1.1 基础正则表达式

1、正则表达式与通配符

  • 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed等命令可以支持正则表达式。
  • 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。

- 2、基础正则表达式
在这里插入图片描述
“ * ”前一个字符匹配0次,或任意多次

grep "a*" test_rule.txt
# 匹配所有内容,包括空白行,和正则表达式测试软件还是有些区别的。
grep "aa*" test_rule.txt
# 匹配至少包含有一个 a 的行
grep "aaa*" test_rule.txt
匹配最少包含两个连续a的字符串
grep "aaaaa*" test_rule.txt
#则会匹配最少包含四个个连续a的字符串

“ . ” 匹配除了换行符外任意一个字符

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

“ ^ ”匹配行首,“$”匹配行尾

grep "^M" test_rule.txt
# 匹配以大写“ M ”开头的行
grep "n$" test_rule.txt
# 匹配以小写“ n ”结尾的行
grep -n "^$" test_rule.txt
# 会匹配空白行

“ [ ] ” 匹配中括号中指定的任意一个字符,只匹配一个字符

grep "^[^a-z]" test_rule.txt
# 匹配不用小写字母开头的行
grep "^[^a-zA-Z]" test_rule.txt
# 匹配不用字母开头的行

“ \ ” 转义符

grep "\.$" test_rule.txt
# 匹配使用“ . ”结尾的行

“ {n} ”表示其前面的字符恰好出现n次(实际上为{ n },但在linux当中需要转义)

grep "a\{3\}" test_rule.txt
# 匹配 a 字母连续出现三次的字符串
grep "[0-9]\{3\}" test_rule.txt
# 匹配包含连续的三个数字的字符串

“ {n,} ”表示其前面的字符出现不小于n次

grep "^[0-9]\{3,\}[a-z]" test_rule.txt
# 匹配最少用连续三个数字开头的行

“{n,m}”匹配其前面的字符至少出现n次,最多出现m次

grep "sa\{1,3\}i" test_rule.txt
# 匹配在字母 s 和字母 i 之间有最少一个 a ,最多三个 a

二、字符截取命令

2.1 cut字段提取命令

[root@localhost ~]# cut [选项] 文件名
选项:
-f 列号:  提取第几列
-d 分隔符: 按照指定分隔符分割列

ps:grep获得符合条件的行。cut获得符合条件的列

[root@localhost ~]# vi student.txt   
ID Name gender Mark      #中间是TAB键形成的空白
1 Liming   M 86
2 Sc M 90
3 Gao M 83
[root@localhost ~]# cut -f 2 student.txt
[root@localhost ~]# cut -f 2,3 student.txt
[root@localhost ~]# cut -d ":" -f 1,3 /etc/passwd       # -d指定分隔符
cat /etc/passwd | grep "/bin/bash" | grep -v root | cut -d ":" -f 1
#可以得到除了root已经创建的用户名

cut命令的局限

[root@localhost ~]# df -h | cut -d " " -f 1,3
#中间以空格分割但是每个字段间的空格个数不同怎么办?awk可以解决,但很复杂。

2.2 printf命令

printf '输出类型输出格式' 输出内容
输出类型:
%ns:  输出字符串。n是数字指代输出几个字符
%ni:  输出整数。n是数字指代输出几个数字
%m.nf:  输出浮点数。m和n是数字,指代输出的整数位数和小数位数。如%8.2f代表共输出8位
         数,其中2位是小数,6位是整数。
输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是Backspace键
\f: 清除屏幕
\n: 换行
\r: 回车,也就是Enter键
\t: 水平输出退格键,也就是Tab键
\v: 垂直输出退格键,也就是Tab键

举几个例子

# ' '中包含的就是输出格式
[root@localhost ~]# printf %s 1 2 3 4     
1234[root@localhost ~]# printf %s %s 1 2 3 4    
%s1234[root@localhost ~]# printf '%s %s' 1 2 3 4
1 23 4[root@localhost ~]# printf '%s %s\n' 1 2 3 4  
1 2
3 4

printf输出文件内容

printf '%s' $(cat student.txt)
#不调整输出格式
printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $(cat student.txt)
#调整格式输出

ps:printf输出文件内容不能直接跟文件名

在awk命令的输出中支持print和printf命令

  • print:print会在每个输出之后自动加入一个换行符(Linux默认没有print命令
  • printf:printf是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符

2.3 awk命令

awk '条件1{动作1} 条件2{动作2}…'  文件名
条件(Pattern):
一般使用关系表达式作为条件
x > 10  判断变量 x是否大于10
x>=10  大于等于
x<=10  小于等于
动作(Action):
格式化输出
流程控制语句
[root@localhost ~]# vim testzz 
id      name    gender  mark
1       lm      M       86
2       sc      M       90
3       gao     M       83
[root@localhost ~]# awk '{print $1 "\t" $3"\n"}' testzz
id      gender

1       M

2       M

3       M

[root@localhost ~]# df -h | awk '{printf $2"\t"$4"\n"}'
容量    可用
16G     14G
341M    341M
353M    353M
353M    347M
353M    353M
8.0G    8.0G
1014M   880M
2.0G    1.8G
2.0G    2.0G
71M     71M

ps:awk读取数据也是先按行去读取,$0代表本行$1代表第一个字符串$2代表第二个字符串。

BEGIN的作用

[root@localhost ~]# awk 'BEGIN{print "this is a test begin"} {print $1 "\t" $3"\n"}' testzz 
this is a test begin
id      gender

1       M

2       M

3       M

END的作用

[root@localhost ~]# awk 'END{print "test end"} {print $1 "\t" $3 "\n"}' testzz            
id      gender

1       M

2       M

3       M

test end

FS可以指定分隔符

[root@localhost ~]# cat /etc/passwd | grep "/bin/bash"|awk '{FS=":"}{print $1"\t" $4}'
root:x:0:0:root:/root:/bin/bash
lingzhiling     1000
hsw     1001
bimm    1002
cangls  1003
st      1005
#因为是先读入数据再指定分隔符所以若不加BEGIN,会出现第一行没有分割的情况下
[root@localhost ~]# cat /etc/passwd | grep "/bin/bash"|awk 'BEGIN{FS=":"}{print $1"\t" $4}'
root    0
lingzhiling     1000
hsw     1001
bimm    1002
cangls  1003
st      1005
-F 分隔符也能达到同样的目的
[root@localhost ~]# cat /etc/passwd | grep "/bin/bash"|awk -F : '{print $1"\t" $4}' 
root    0
lingzhiling     1000
hsw     1001
bimm    1002
cangls  1003
st      1005

关系运算符

[root@localhost ~]# vim testzz 
id      name    gender  mark
1       lm      M       86
2       sc      M       90
3       gao     M       83
[root@localhost ~]# cat testzz |grep -v id | awk '$4>85 {print $2}' 
lm
sc

2.4 sed命令
sed 是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。主要对命令结果的操作上。

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

举一些例子

[root@localhost ~]# vim testzz 
id      name    gender  mark
1       lm      M       86
2       sc      M       90
3       gao     M       83
  • 行数据操作
[root@localhost ~]# sed '2p' testzz 
id      name    gender  mark
1       lm      M       86
1       lm      M       86
2       sc      M       90
3       gao     M       83
#查看文件的第二行,会发现把所有数据都显示出来了

[root@localhost ~]# sed -n '2p' testzz 
1       lm      M       86
#只显示要搜索打的数据

[root@localhost ~]# sed '2,3d' testzz 
id      name    gender  mark
3       gao     M       83
#删除2-3行的数据但不会修改文件本身

[root@localhost ~]# sed '2a hello' testzz 
id      name    gender  mark
1       lm      M       86
hello
2       sc      M       90
3       gao     M       83
# 在第二行后追加 hello

[root@localhost ~]# sed '2a hello \   #注意回车才行
> world' testzz            
id      name    gender  mark
1       lm      M       86
hello
world
2       sc      M       90
3       gao     M       83
# 在第二行前插入两行数据

[root@localhost ~]# sed '2c no such person' testzz 
id      name    gender  mark
no such person
2       sc      M       90
3       gao     M       83
# 数据行替换
  • 字符串替换
#格式:sed ‘s/旧字串/新字串/g’ 文件名
[root@localhost ~]# sed '2s/lm/hao/g' testzz 
id      name    gender  mark
1       hao     M       86
2       sc      M       90
3       gao     M       83

[root@localhost ~]# sed -e '2s/86/60/g;3s/90/100/g' testzz   
id      name    gender  mark
1       lm      M       60
2       sc      M       100
3       gao     M       83**加粗样式**
#利用-e 进行多处修改; 

三、字符处理命令

1、排序命令sort

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

例子

[root@localhost ~]# sort /etc/passwd
# 排序用户信息文件
[root@localhost ~]# sort -r /etc/passwd
# 反向排序
[root@localhost ~]# sort -t ":" -k 3,3 /etc/passwd
# 指定分隔符是“:”,用第三字段开头,第三字段结尾排序,就是只用第三字段排序,但是这是当成字符串排的,会发现有不符合原意的存在。
[root@localhost ~]# sort -n -t ":" -k 3,3 /etc/passwd
#用这个

2、统计命令wc

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

条件判断

1、按照文件类型进行判断
在这里插入图片描述两种判断格式

[root@localhost ~]# test -e /root/install.log
[root@localhost ~]# [ -e /root/install.log ]   #注意有空格
[ -d /root ] && echo "yes" || echo "no"
# 第一个判断命令如果正确执行,则打印“ yes ”,否则打印“ no ”

2、按照文件权限进行判断

在这里插入代码片ps:权限是只要ugo其中一个有权限就会判断为真。

[ -w student.txt ] && echo "yes" || echo "no"
# 判断文件是拥有写权限的

3、两个文件之间进行比较

在这里插入图片描述

[root@localhost tmp]# ln abc bcd
#来个硬链接
[root@localhost tmp]# [ /tmp/abc -ef /tmp/bcd ] && echo yes ||echo no   
yes
#inode相同输出yes

4、两个整数之间比较
在这里插入图片描述
举例子

[ 23 -ge 22 ] && echo "yes" || echo "no"
yes
# 判断 23 是否大于等于 22 ,当然是了
[ 23 -le 22 ] && echo "yes" || echo "no"
no
# 判断 23 是否小于等于 22 ,当然不是了

5、字符串的判断
在这里插入图片描述例子

[root@localhost tmp]# name=hhh
# 给 name 变量赋值
[root@localhost tmp]# [ -z $name ] && echo yes || echo no
no
# 判断 name 变量是否为空,因为不为空,所以返回 no
aa=11
bb=22
# 给变量 aa 和变量 bb 赋值
[ "$aa" == "bb" ] && echo "yes" || echo "no"
no
# 判断两个变量的值是否相等,明显不相等,所以返回 no

6、多重条件判断
在这里插入图片描述例子

aa=11
[ -n "$aa" -a "$aa" -gt 23 ] && echo "yes" || echo "no"
no
# 判断变量 aa 是否有值,同时判断变量 aa 的是否大于 23
# 因为变量 aa 的值不大于 23 ,所以虽然第一个判断值为真,
返回的结果也是假

五 流程控制

5.1 if语句

1、 单分支if条件语句

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

单分支条件语句需要注意几个点

  • if语句使用fi结尾,和一般语言使用大括号结尾不同
  • [ 条件判断式 ]就是使用test命令判断,所以中括号和条件判断式之间必须有空格
  • then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了

2、双分支if条件语句

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

例子

#占用百分比判断
[root@localhost sh]# vim ducument.sh 
#!/bin/bash
#Author hsw (qq:110)
result=$( df -h | grep "centos-root" | awk '{printf $5}' | cut -d "%" -f
 1)
if [ $result -le 50 ]
then
echo "safe"
fi
[root@localhost sh]# ./ducument.sh   
safe

例子1:备份mysql数据库

[root@localhost sh]# vim back-up 
ntpdate asia.pool.ntp.org &> /dev/null
#同步系统时间
date=$(date +%y%m%d)
#把当前系统时间按照年月日格式赋予变量date
size=$(du -sh /usr/lib64/mysql)
#统计mysql数据库的大小,并把大小赋予size变量。
if [ -d /tmp/dbbak ]
        then
                echo "Date:$date" > /tmp/dbbak/info.txt
                echo "Size:$size" >> /tmp/dbbak/info.txt
                cd /tmp/dbbak
                tar -zcPf bake-up-$date.tar.gz /usr/lib64/mysql /tmp/dbbak/info.txt & >/dev/null
        else
                mkdir /tmp/dbbak
                echo "Date:$date" > /tmp/dbbak/info.txt
                echo "Size:$size" >> /tmp/dbbak/info.txt
                cd /tmp/dbbak
                tar -zcPf  bake-up-$date.tar.gz /usr/lib64/mysql /tmp/dbbak/info.txt & >/dev/null
fi

例子2:判断apache是否启动

#!/bin/bash
port=$(nmap -sT 192.168.43.200 | grep tcp | grep http | 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-err.log
fi

3、 多分支if条件语句

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

例子

[root@localhost sh]# vim elif    
#!/bin/bash
#Author hsw
echo "please input a file name"
name=$1
if [ -z "$name" ]
        then
                echo "null,please input a not null"
                exit 1
elif [ ! -e "$name" ]
        then
                echo "file is not exist"
                exit 2
elif [ -f "$name" ]
        then
                echo "this is a file"
elif [ -d "$name" ]
        then
                echo "this is a directory"
else
        echo "this is an other file"
fi

5.2 case语句

多分支case条件语句
case语句和if…elif…else语句一样都是多分支条件语句,不过和if多分支条件语句不同的是,case语句只能判断一种条件关系,而if语句可以判断多种条件关系。

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

例子

[root@localhost sh]# vim case
#!/bin/bash
#Author hsw
read -p "input your choose yes/no   " -t 30 cho
case $cho in
        "yes")
                echo "Your chose is yes"
                ;;
        "no")
                echo "Your chose is no"
                ;;
        *)
                echo "Your chose is error"
                ;;
esac

5.3 for循环

语法一

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

例子

#注意这种格式的sao
cd /lamp
ls *.tar.gz > ls.log
for i in $ (cat ls.log)
	do
			tar -zxf $i &> /dev/null
	done
rm -rf /lamp/ls.log

语法二

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

例子

[root@localhost sh]# vim sum
#!/bin/bash
sum=0
for(( i=1;i<101;i++ ))
        do
                sum=$(($sum+$i))
        done                            
echo $sum    

5.4 while循环与until循环

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

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

例子

[root@localhost sh]# vim sum
#!/bin/bash
#sum
#Author hsw
i=1
sum=0
while [ $i -le 100 ]
        do
                sum=$(($sum+$i ))
                i=$(( $i+1 ))
        done
echo "sum is $sum"

2、until循环

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

until [ 条件判断式 ]
do
程序
done

例子

[root@localhost sh]# vim sum
#!/bin/bash
#sum
#Author hsw
i=1
sum=0
until [ $i -ge 101 ]
        do
                sum=$(($sum+$i ))
                i=$(( $i+1 ))
        done
echo "sum is $sum"

猜你喜欢

转载自blog.csdn.net/weixin_44406146/article/details/92429434