linux运维--shell编程(2)

1、正则表达式

什么时正则表达式?与通配符有什么区别?——— 正则表达式一般是在文件中搜索内容,是包含匹配;而通配符表示是在文件夹中搜索文件,是完全匹配;

grep、awk、sed等命令都可以支持正则表达式,而ls、find、cp等是不支持正则表达式。

基础正则表达式其相关元字符以及含义如下表所示:

以上需要记住;

扩展正则表达式

扩展正则表达式需要使用grep -E命令,一般使用的也不是很多。其元字符和具体含义如下表所示:

知道就行;

范例1:匹配邮箱

[0-9a-zA-Z_]+@[0-9a-zA-Z_]+(\.[0-9a-zA-Z_]+){1,3}

范例2:匹配IP

^(([0-9]\.)|([1-9][0-9]\.)|(1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)){3}(([0-9]\.)|([1-9][0-9]\.)|(1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.))$

2、字符截取和替换命令

cut提取命令

         如下,一般前面两条使用比较多。cut的默认分隔符是制表符(tab键),对于空格符来做分隔符不支持;

       对于要提取多列,列与列之间用逗号“,”隔开即可。

awk编程

当用空格来做分割符号时,cut就不能直接提取行了,需要用到awk来进行行提取。了解awk之前需要先学习printf函数,一般与awk搭配使用。

printf格式化输出

       其中printf表达式中输出内容一般是执行某条命令的结果。例如printf '%s \t %s \t %s \t \n' $(cat test.txt),个人理解文件内容默认使用空格进行分隔了,其中printf表达式中输出类型输出格式中的空格不会体现在printf的输出结果中。

awk基本使用

注意,对于没有条件的awk命令,直接按动作中的内容进行输出。

示例1:输出文件test.txt的第一列与第三列

awk '{printf $2 "\t" $3 "\n"}' test.txt

示例2:输出df -h返回的/dev/sda1行的第五列与第6列内容。此时使用的是print,默认最后自带换行

[root@jone ~]# df -h
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root   23G  1.7G   22G    8% /
devtmpfs                 232M     0  232M    0% /dev
tmpfs                    244M     0  244M    0% /dev/shm
tmpfs                    244M  4.5M  240M    2% /run
tmpfs                    244M     0  244M    0% /sys/fs/cgroup
/dev/sda1               1014M  132M  883M   13% /boot
tmpfs                     49M     0   49M    0% /run/user/0
[root@jone ~]# df -h | grep /dev/sda1 | awk '{print $5 "\t" $6}'
13%	/boot

awk与cut配合使用:

[root@jone ~]# df -h | grep /dev/sda1 | awk '{print $5}' | cut -d "%" -f 1
13

awk条件判断:

注意,BEGIN是awk程序一开始时还未读取数据前执行,END则是处理完数据后执行。

awk内置变量如下:(主要是FS及之前的几个常用,其他的用的少)

一般这些内置变量和条件判断、awk基本语法都是综合运用的;

举例1:用:分隔符对passwd中的内容进行分隔,输出第三列为1000的用户名

备注:由于awk默认先读取第一行$0,不加BEGIN参数时不会对第一行进行:分隔而是直接输出。另外,awk的内容读取时逐行进行读取的;

[root@jone ~]# cat /etc/passwd | grep "/bin/bash"
root:x:0:0:root:/root:/bin/bash
zhangli:x:1000:1000:zhangli:/home/zhangli:/bin/bash
li:x:1001:1001::/home/li:/bin/bash

[root@jone ~]# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN{FS=":"} $3=="1000" {print($1)}'
zhangli

举例2:用:进行分隔,并输出第一列和第三列的数值,写出其行号和字段数(理解也是列数)

[root@jone ~]# cat /etc/passwd | grep /bin/bash
root:x:0:0:root:/root:/bin/bash
zhangli:x:1000:1000:zhangli:/home/zhangli:/bin/bash
li:x:1001:1001::/home/li:/bin/bash

[root@jone ~]# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf($1 "\t" $3 "\t 行号:" NR "\t 字段数:" NF "\n")}'
root	0	 行号:1	 字段数:7
zhangli	1000	 行号:2	 字段数:7
li	1001	 行号:3	 字段数:7
[root@jone ~]# 

sed命令

一般在程序修改数据,使用sed对数据进行增删改查。

举例1:在test.txt文件的第二行后添加一行,内容为1111,这种方式不会直接修改文件,只是显示

[root@jone ~]# sed '2a 1111' test.txt 
num   name   score
1    zl      99
1111
2    ls      98
3    ts      99
4    wk      78

举例2:在例子1基础上,若要直接修改文件则需要加-i参数

[root@jone ~]# sed  -i '2a 1111' test.txt
[root@jone ~]# cat test.txt 
num   name   score
1    zl      99
1111
2    ls      98
3    ts      99
4    wk      78
[root@jone ~]# 

举例3:对文件test.txt中内容,删除第二行

sed -i '2d' test.txt 

举例4:对文件test.txt中的内容,替换某个字段

不注明行范围,表示对整个文件的内容字段进行替换

sed 's/zl/zm/g' test.txt

其他的请参考命令说明即可。

字符处理命令

sort排序命令

实例1:将/etc/passwd文件以:作为分隔符,按第三列的数值大小顺序进行排序

[root@jone ~]# sort -n -t ":" -k 3,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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dhcpd:x:177:177:DHCP server:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
zhangli:x:1000:1000:zhangli:/home/zhangli:/bin/bash
li:x:1001:1001::/home/li:/bin/bash
zhang:x:1002:1002::/home/zhang:/sbin/nologin
lisi:x:1003:1003::/home/lisi:/sbin/nologin
user1:x:1004:1004::/home/user1:/sbin/nologin

uniq

取消重复行,等价于sort -u,这样保证在输出内容时重复行只输出一行(只比较相邻两行);

wc

统计命令,之前已经学习过,不再讲;

uniq与sort -u

        由于uniq只是检查相邻两行重复情况,而sort -u进行去重时会对原有数据进行排序。对于针对即要去重又要保持原有序列的需求时候,sort与uniq就比较难搞,通过下面的办法来进行实现:

cat 【对应文本】 |awk '{if(!($0 in a)){print $0};a[$0];}' > result.txt(重定向到result.txt文件)

条件判断

1、按文件类型进行判断 

图中标红的为常用功能项。一般格式为[ 测试选项 文件 ],一般用在if语句中。 

举例:测试/etc/passwd这个文件是否存在并是否为非空

[root@jone ~]# [ -s /etc/passwd ] && echo yes || echo no
yes

2、按文件权限进行判断

举例,判断文件/etc/passwd是否具有写权限,其实是判断整个,只要有写权限都会是真

[root@jone ~]# ll /etc/passwd
-rw-r--r-- 1 root root 1163 12月 15 23:04 /etc/passwd
[root@jone ~]# 
[root@jone ~]# [ -w /etc/passwd ] && echo yes || echo no
yes

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

一般第三个用的还稍微多点,其他用的不多。

4、两个整数之间进行比较

比较简单,不进行细讲了

5、字符串的判断

6、多重条件判断

流程控制语句

if单分支

其格式如下:条件判断式使用上面所讲的test判断式,条件判断式与中括号间都是有空格的。

或者

举例:取出/dev/sda1的磁盘利用率,如果大于10就报警111111

[root@jone ~]# cat dd.sh 
#!/bin/bash

aa=$(df -h | grep /dev/sda1 | awk '{print $5}' | cut -d "%" -f 1)
if [ "$aa" -ge 10 ]
	then
		echo "111111"
fi

if双分支

增加一个知识点:一般执行脚本过程中不想要看相关的输出,因为没什么意义,因而可以把对应输出(正确或错误)直接&>放进/dev/null(垃圾箱)中。

if多分支

举例:linux里做一个计算器

[root@jone ~]# cat caculator.sh 
#!/bin/bash

echo "欢迎使用计算器"

read -t 30 -p "please input a number1: " num1
read -t 30 -p "please input a number2: " num2
read -t 30 -p 'please input a operator:+-*/ ' oper

if [ -n "$num1" -a -n "$num2" -a -n "$oper" ]
	then
		test1=$( echo "$num1" | sed 's/[0-9]//g' )
		test2=$( echo "$num2" | sed 's/[0-9]//g' )
		if [ -z "$test1" -a -z "$test2" ]
			then
			if [ "$oper" == "+" ]
				then
					sum=$(($num1+$num2))
			elif [ "$oper" == "-" ]
				then
					sum=$(($num1-$num2))
			elif [ "$oper" == "*" ]
				then
					sum=$(($num1*$num2))
			elif [ "$oper" == '/' ]
				then
					sum=$(($num1/$num2))
			else
				echo "the format of operator input is wrong: $oper "
				exit 10
			fi
			else
				echo "the format of input is wrong: $num1,$num2"
                		exit 11
		fi
else
	echo "请输入对应的内容"
	exit 20
fi
echo "$num1 $oper $num2 = $sum " 

case语句

做的一层判断。if多分支可以做多层判断。case语句语法格式为:

举例:简单一层判断,可以简化代码

[root@jone ~]# cat case.sh 
#!/bin/bash

echo "wantobeijing,please choose 1"
echo "wantoshanghai,please choose 2"
echo "wantochengdu,please choose 3"

read -t 30 -p "please input your choice: " choice

case $choice in
	"1")
		echo "beijing11111"
		;;
	"2") 
		echo "shanghai22222"
		;;
	"3")
		echo "chengdu33333"
		;;
	*)
		echo "error input"
		;;
esac

for循环语句

其语法如下,都在用,都重要。

语法1:

语法2:

语法1举例:

[root@jone ~]# cat for.sh 
#!/bin/bash

for i in 1 2 3
	do
		echo $i
	done

语法2举例:

[root@jone ~]# cat for2.sh 
#!/bin/bash

sum=0

for (( i=1;i<=100;i=i+1 ))
	do
		sum=$(( $sum+$i ))
	done
echo $sum

在某些时候语法1比语法2更是合适在shell脚本语言里进行编程。

例如:过滤目录中的压缩文件并对其进行操作,下面那种语法相对更简单,for i in $(命令)也是对$(命令)输出内容的每一行/空格间隔开的数进行遍历;

while循环

语法如下:

举例:

[root@jone ~]# cat while.sh 

#!/bin/bash

i=1
s=0

while [ $i -le 100 ]
do
	s=$(( $s+$i ))
	i=$(( $i+1 ))
done

echo $s

until语句

语法如下,与while语句意思相反,当条件判断式不成立时执行下面的语句;

例子:

[root@jone ~]# cat until.sh 
#!/bin/bash
i=1
s=0

until [ $i -gt 100 ]
do
	s=$(( $s+$i ))
	i=$(( $i+1 ))
done
echo $s

exit语句

已经说过,不再讲

break与continue

语法与C语言中的break和continue类似,不再讲述

举例:

[root@jone ~]# cat break.sh 
#!/bin/bash

for (( i=1;i<=10;i++ ))
do
	if [ "$i" == 4 ]
	then
		continue
	fi
	echo "$i"
done

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值