Shell脚本编程

Shell脚本编程

 

一. SHELL入门

1.1 变量

1.1.1 变量名规范

  • 变量是由任何字母、数字、下划线组成的字符串,且不能以数字开头。
  • 区分字母大小写
  • 变量、等号、值中间不能出现任何空格

实例
在这里插入图片描述

注:$ var1+$ var2并不能实现相加,$ var1,$ var2默认作为字符串来处理

1.1.2 位置变量

当一条命令或脚本执行时,后面可以跟多个参数,我们使用位置参数变量来表示这些参数。

位置参数变量描述
$nn 为数字,$ 0 代表Shell本身的文件名,$ 1〜$ 9 代表第 1 ~ 9 个参数,10 以上的参数需要用大括号包含, 如 $ {10}
$*命令行所有参数,把所有的参数看成一个整体
$@命令行中所有参数,但每个参数区别对待
$#命令行中所有参数的个数

实例
在这里插入图片描述

$ @和$ *都表示命令行所有参数,但是$ *将命令行的所有参数看成一个整体,而$ @则区分各个参数

1.1.3 环境变量

环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或多个应用程序将使用到的信息。Linux是一个多用户的操作系统,每个用户登录系统时都会有一个专用的运行环境,通常情况下每个用户的默认的环境都是相同的。这个默认环境就是一组环境变量的定义。每个用户都可以通过修改环境变量的方式对自己的运行环境进行配置。

分类

  • 对所有用户生效的环境变量 /etc/profile

  • 对特定用户生效的环境变量 ~ /.bashrc或者~/.bash_profile

  • 临时有效的环境变量 export

常用环境变量

环境变量含义
PATH命令搜索的路径
HOME用户家目录的路径
LOGNAME用户登录名
PWD当前所在路径
HISTFILE历史命令的保存文件
HISTSIZE历史命令保存的最大行数
HOSTNAME主机名
SHELL用户当前使用的SHELL
PS1一级命令提示符
TMOUT用户和系统交互过程的超时值
IFS系统输入分隔符
OFS系统输出分隔符

实例
在这里插入图片描述

1.2 管道

将一个命令的输出作为另一个命令的输入

实例

  • 列出所有安装过的软件包
rpm -qa

rpm命令是RPM软件包的管理工具
  • 1列出与python相关的软件包
rpm -qa | grep python


Linux grep 命令用于查找文件里符合条件的字符串。
    -a :将 binary 文件以 text 文件的方式搜寻数据
    -c :打印匹配次数
    -f  两个文件相同行  如,grep -f file1 file2
    -h 不显示匹配行所在文件名
    -i :忽略大小写的不同,所以大小写视为相同
    -l 只显示匹配到的文件名
    -n :顺便输出行号
    -o 只显示匹配的字符
    -v :只显示不匹配的行。 
    --color=auto :可以将找到的关键词部分加上颜色的显示喔!
  •  
  • 显示与python相关的软件包的行数
rpm -qa | grep python | wc -l


Linux wc命令用于计算字数
    -c或--bytes或--chars 只显示Bytes数。
    -l或--lines 只显示行数。
    -w或--words 只显示字数。
    --help 在线帮助。
    --version 显示版本信息。
  • 1

1.3 退出状态码

1.3.1 退出状态码描述

所有的shell命令都使用退出状态吗来告知shell它已执行完毕

退出状态码是一个0~255的整数值

Linux提供了一个$?来捕获退出状态码的值,所以,可以通过echo语句测试命令是否运行成功。

一般来讲,退出状态 0 表示正常执行,没有遭遇任何问题。其他非零的状态码均表示失败。

状态码描述
0命令成功结束
1一般性未知错误
2不适合的shell 命令
126找到了该命令但无法执行
127没找到命令
128无效的退出参数
128+x与linux信号x相关的严重错误
130通过ctrl+C终止的命令
255正常范围之外的退出状态码

实例
在这里插入图片描述

1.3.2 改变退出状态码的exit命令

退出状态码是以上一条指令的返回结果为准
使用exit命令改变退出状态码

exit $exit_code

exit 48 或者 exit 125 或者exit 0
  • 1

二. 判断与控制

2.1 if-then 语句

语法:

if command | condition     
then 
    commands
fi
  • 1

实例

#!/bin/bash

if pwd
then 
	echo "It works"
fi
  • 1

在这里插入图片描述

2.2 if-then-else 语句

语法:

if command | condition     
then 
    commands
else
    commands
fi
  • 1实例
#!/bin/bash

if pwd
then 
	echo "It works"
fi
  •  

2.3 嵌套if语句

语法:

if command | condition     
then 
    commands
elif command | condition 
then
    commands
else
    commands
fi
  • 1

2.4 条件测试-数值比较

语法:

if condition     
then 
    commands
fi

或者

if condition;then 
    commands
fi
  • 1

数值比较

数值比较含义
n1 -eq n2n1和n2相等,则返回true;否则返回false
n1 -ne n2n1和n2不相等,则返回true;否则返回false
n1 -gt n2n1大于n2,则返回true;否则返回false
n1 -ge n2n1大于等于n2,则返回true;否则返回false
n1 -lt n2n1小于n2,则返回true;否则返回false
n1 -le n2n1小于等于n2,则返回true;否则返回false

实例

#!/bin/bash

if [ $1 -eq $2 ];then 
	echo "$1 = $2"
elif [ $1 -gt $2 ];then 
	echo "$1 > $2"
elif [ $1 -lt $2 ];then 
	echo "$1 < $2"
fi
        
  • 1

在这里插入图片描述

2.5 条件测试-字符串比较

字符串比较

字符串比较含义
str1 = str2相等比较
str1 != str2不相等比较
str1 < str2str1小于str2为true
str1 > str2str1大于str2为true
-n str1str1长度不是0则为true
-z str1str1长度是0则为true

实例

#!/bin/bash
var1='hello'
var2='world'
if [ $var1 = $var2 ];then 
	echo "equal"
else
	echo "not equal"
fi
  • 1

在这里插入图片描述

#!/bin/bash
var1='hello'
var2='world'
if [ $var1 < $var2 ];then 
	echo "<"
else
	echo ">"
fi
  • 1

在这里插入图片描述<被当作了重定向,需要进行转义

#!/bin/bash
var1='hello'var2='world'
if [ $var1 \< $var2 ];then 
	echo "<"
else
	echo ">"
fi
  • 1

在这里插入图片描述

#!/bin/bash
var1=''
var2='world'
if [ -n "$var1" ];then 
	echo "var1 is not null"
else
	echo "var1 is null"
fi
  • 1

在这里插入图片描述

2.6 条件测试-文件比较

文件比较

文件比较含义
-d filefile是否为目录
-f filefile是否为文件
-e filefile是否存在
-r filefile是否可读
-w filefile是否可写
-x filefile是否可执行
-s filefile存在且非空
file1 -nt file2file1比file2新为true
file1 -ot file2file1比file2旧为true

实例

#!/bin/bash

if [ -d /usr/local ];then 
	echo "yes"
else
	echo "no"
fi
  • 1

在这里插入图片描述

#!/bin/bash

if [ /usr/local/test1  -nt /usr/local/test2 ];then 
	echo "new"
else
	echo "old"
fi
  • 1

在这里插入图片描述

2.7 符合条件测试

语法:

语法1 “与”
if condition1 && condition2  
then 
    commands
fi

语法2 “或”

if condition1 || condition2  
then 
    commands
fi
  • 1

实例

#!/bin/bash

var1=56
var2=34
var3=89
if [ $var1 -gt $var2 ] && [ $var2 -lt $var3 ];then 
	echo " $var1 > $var2 并且  $var2 < $var3"
fi
  • 1

在这里插入图片描述

2.8 if-then中使用双括号

使用双括号进行算术运算

语法:

if ((expression))
then 
    commands
fi
  • 1

注:

  • 双括号结构中,变量名引用可以加$,也可以不加

  • 运算符前后可以有空格,也可以没有

  • 可以用于if,for,while等循环控制结构中

  • 多个运算符使用逗号分隔

可用运算符

运算符含义
value++后增
value–后减
++value先增
–value先减
!逻辑求反
==相等
>大于
<小于
>=大于等于
<=小于等于
&&逻辑与
  

实例

#!/bin/bash
a=10
((a+=10))
echo $a
  • 1

在这里插入图片描述

2.9 if-then中使用双方括号

单方括号语法

if [ $n1 -gt $n2 ] && [ $n2 -lt $n3 ]   
then 
    commands
fi

改为双方括号语法

if [ [$n1 -gt $n2  &&  $n2 -lt $n3 ]]   
then 
    commands
fi
  •  
注:
    双括号结构中,变量名引用必须加$
    [[后面必须要空格,]]前面必须有空格
  • 1

2.10 case命令

语法:

case $var in
	pattern1)
		commands
		;;
	pattern2)
		commands;
		;;
esac
  • 1

实例:

#!/bin/bash
case $1 in
	jack)
		echo "hello,jack"
		;;
	mike)
		echo "hello,mike"
		;;
	*)
		echo "hello everyone"
		;;
esac
  • 1

在这里插入图片描述

三. 循环与控制

3.1 for循环

循环遍历一系列特定值,然后在结构体中针对每个特定值做处理

语法:

for var in list
do 
	commands
done
  • 1

实例:

for循环读取列表值:

#!/bin/bash
for i in Beijing Shanghai Nanjing Guangzhou Zhengzhou
do 
	echo "Province is $i"
done

for i in {1..20}
do 
	echo "Number is $i"
done
  • 1

在这里插入图片描述

for循环读取变量值:

#!/bin/bash
list="Zhangsan Lisi Mike Tom"
for i in $list
do 
	echo "Name is $i"
done          
  •  

在这里插入图片描述

#!/bin/bash

IFS=$":" #分隔符,默认为空格或tab

list="Zhangsan:Lisi:Mike:Tom"
for i in $list
do 
	echo "Name is $i"
done
  • 1

在这里插入图片描述

for循环从命令执行结果读取值

#!/bin/bash

FILE=$(ls /opt/)

for i in $FILE
do 
	echo "file is $i"
done
  • 1

在这里插入图片描述

#!/bin/bash

for i in $(ls /opt/)
do 
	if [ -d /opt/$i ]
	then
		echo "$i is DIR"
	elif [ -f /opt/$i ]
	then
		echo "$i is FILE"
	fi
done
  • 1

在这里插入图片描述

C语言风格的for循环

#!/bin/bash

for ((i=10;i<20;i++))
do 
	echo "Next Number is $i"
done
  • 1

在这里插入图片描述

#!/bin/bash
sum=0
for (( i=1;i<101;i++))
do 
	(( sum+=$i ))	
done
echo "sum is $sum"
  • 1

在这里插入图片描述

3.2 while循环

语法:

while command
do 
	commands
done

实例:

#!/bin/bash
num=10
while [ $num -lt 20 ]
do 
	echo "number is $num"
	((num++))
done
  •  

在这里插入图片描述

3.3 until命令

语法:

until command
do 
	commands
done
  • 1

实例:

#!/bin/bash
num=10
until [ $num -eq 0 ]
do 
	echo "number is $num"
	((num--))
done

在这里插入图片描述

3.4 break命令

实例:

#!/bin/bash
num=10
for ((i=1;i<=10;i++))
do
	if ((i==5))
	then
		break
	 else
		echo "number is $i"
	fi
done
  • 1

在这里插入图片描述

当有两层循环的时候,"break 1"跳出内循环; " break 2"跳出外循环

#!/bin/bash
num=10
for ((i=1;i<=10;i++))
do
	for((j=1;j<=5;j++))
	do
		
		if ((j==3))
			then
				break 1
			 else
				echo "$i $j"
			fi
	done
done
  • 1

在这里插入图片描述

#!/bin/bash
num=10
for ((i=1;i<=10;i++))
do
	for((j=1;j<=5;j++))
	do
		
		if ((j==3))
			then
				break 2
			 else
				echo "$i $j"
			fi
	done
done

在这里插入图片描述

3.5 continue命令

实例:

#!/bin/bash
num=10
for ((i=1;i<=30;i++))
do
	if ((i>15 && i<25))
	then
				continue
	else
				echo "Number is $i"
	fi
done
  • 1

在这里插入图片描述

3.6 处理循环的输出

实例

#!/bin/bash
num=10
for ((i=1;i<=100;i++))
do
	echo "Number is $i"

done > result.txt
  • 1

在这里插入图片描述

#!/bin/bash
num=10
for ((i=1;i<=100;i++))
do
	echo "Number is $i"

done | grep "5"
  • 1

在这里插入图片描述

四. 变量的高级用法

4.1 变量替换和测试

变量替换

语法含义
${变量名#匹配规则}从变量开头进行规则匹配,将符合最短的数据删除
${变量名##匹配规则}从变量开头进行规则匹配,将符合最长的数据删除
${变量名%匹配规则}从变量尾部进行规则匹配,将符合最短的数据删除
${变量名%%匹配规则}从变量尾部进行规则匹配,将符合最长的数据删除
${变量名/旧字符串/新字符串}变量内容符合旧字符串规则,则第一个旧字符串会被新字符串取代
${变量名//旧字符串/新字符串}变量内容符合旧字符串规则,则全部的旧字符串会被新字符串取代

实例
在这里插入图片描述

变量测试

在这里插入图片描述

实例

在这里插入图片描述

4.2 字符串处理

计算字符串长度

方法一:
${#string}

方法二:
expr length "$string"  #string如果有空格,则必须加双引号
  • 1

获取子串在字符串中的索引位置

语法

expr index $string $substring
  • 1

在这里插入图片描述

$substring会被切割成字符,比如orl被切割成o,r,l,分别查找字符,哪个字符最先找到就会返回那个字符的位置,l最靠前,位置为3,返回3

计算子串长度

expr match $string substr
  • 1

在这里插入图片描述
$string会从头开始匹配子串,不能从中间匹配

抽取子串

方法一:
${string:position}                       #从string中的position开始

方法二:
${string:position:length}                 #从position开始,匹配长度为length

方法三:
${string:-(position)}                       #从右边开始匹配   

方法四:
${string:(position)}                      #从左边开始匹配   

方法五:
expr substr $string $position $length     #从position开始,匹配长度为length
  • 1

在这里插入图片描述
练习

需求描述:
变量string=“Bigdata process framework is Hadoop,Hadoop is an open source project” 执行脚本后,打印输出string字符串变量,并给出用户以下选项:

  • 打印string长度
  • 删除字符串中所有的Hadoop
  • 替换第一个Hadoop为Mapreduce
  • 替换全部Hadoop为Mapreduce

用户输入数字1|2|3|4,可以执行对应项的功能;输入qlQ则退出交互模式

脚本:

read命令用于从标准输入中读取输入单行
 -a:将分裂后的字段依次存储到指定的数组中,存储的起始位置从数组的index=0开始。
 -d:指定读取行的结束符号。默认结束符号为换行符。
 -n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取。
 -N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束。其中换行符或回车算一个字符。
 -p:给出提示符。默认不支持"\n"换行,要换行需要特殊处理,见下文示例。例如,"-p 请输入密码:"
 -r:禁止反斜线的转义功能。这意味着"\"会变成文本的一部分。
 -s:静默模式。输入的内容不会回显在屏幕上。
 -t:给出超时时间,在达到超时时间时,read退出并返回错误。也就是说不会读取任何内容,即使已经输入了一部分。
 -u:从给定文件描述符(fd=N)中读取数据。
#!/usr/bin/env bash

string="Bigdata process framework is Hadoop,Hadoop is an open source project"

function tips_info
{
	echo "******************************************"
	echo "***  (1) 打印string长度"
	echo "***  (2) 在整个字符串中删除Hadoop"
	echo "***  (3) 替换第一个Hadoop为Mapreduce"
	echo "***  (4) 替换全部Hadoop为Mapreduce"
	echo "******************************************"
}

function print_len
{
	if [ -z "$string" ];then
		echo "Error,string is null"
		exit 1
	else
		echo "${#string}"
	fi
}

function del_hadoop
{
	if [ -z "$string" ];then
		echo "Error,string is null"
		exit 1
	else
		echo "${string//Hadoop/}"
	fi
}

function rep_hadoop_mapreduce_first
{
	if [ -z "$string" ];then
		echo "Error,string is null"
		exit 1
	else
		echo "${string/Hadoop/Mapreduce}"
	fi
}

function rep_hadoop_mapreduce_all
{
        if [ -z "$string" ];then
                echo "Error,string is null"
                exit 1
        else
                echo "${string//Hadoop/Mapreduce}"
        fi
}


while true
do

echo "【string=\"$string\"】"
tips_info
read -p "Pls input your choice(1|2|3|4|q|Q):" choice
case "$choice" in
	1)
		echo
		echo "Length Of String is: `print_len`"
		echo
		continue
		;;
	2)
		echo
		echo "删除Hadoop后的字符串为:`del_hadoop`"
		echo
		;;
	3)
		echo 
		echo "替换第一个Hadoop的字符串为:`rep_hadoop_mapreduce_first`"
		echo
		;;
	4)
		echo 
                echo "替换第一个Hadoop的字符串为:`rep_hadoop_mapreduce_all`"
                echo
		;;
	q|Q)
		exit 0
		;;
	*)
		echo "error,unlegal input,legal input only in { 1|2|3|4|q|Q }"
		continue	
		;;
esac
done
  • 1
  •  
  • 40在这里插入图片描述

4.3 命令替换

语法格式

方法一
`command`

方法二
$(command)

$(())两个括号用来进行,包括加减乘除数据运算,引用变量前面可以加$,也可以不加$

  •  

案例

获取系统的所有用户并输出

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。

参数:

    -b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
    -c :以字符为单位进行分割。
    -d :自定义分隔符,默认为制表符。
    -f :与-d一起使用,指定显示哪个区域。
    -n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的范围之内,该字符将被写出;否则,该字符将被排除
#!/bin/bash
index=1

for user in `cat /etc/passwd | cut -d ":" -f 1`
do
	echo "This is $index user: $user"
	index=$(($index + 1))
done

  •  

在这里插入图片描述

根据系统时间计算今年或明年

Linux date命令可以用来显示或设定系统的日期与时间

时间方面:

    % : 印出 %
    %n : 下一行
    %t : 跳格
    %H : 小时(00..23)
    %I : 小时(01..12)
    %k : 小时(0..23)
    %l : 小时(1..12)
    %M : 分钟(00..59)
    %p : 显示本地 AM 或 PM
    %r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M)
    %s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数
    %S : 秒(00..61)
    %T : 直接显示时间 (24 小时制)
    %X : 相当于 %H:%M:%S
    %Z : 显示时区

日期方面:

    %a : 星期几 (Sun..Sat)
    %A : 星期几 (Sunday..Saturday)
    %b : 月份 (Jan..Dec)
    %B : 月份 (January..December)
    %c : 直接显示日期与时间
    %d : 日 (01..31)
    %D : 直接显示日期 (mm/dd/yy)
    %h : 同 %b
    %j : 一年中的第几天 (001..366)
    %m : 月份 (01..12)
    %U : 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形)
    %w : 一周中的第几天 (0..6)
    %W : 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形)
    %x : 直接显示日期 (mm/dd/yy)
    %y : 年份的最后两位数字 (00.99)
    %Y : 完整年份 (0000..9999)


参数说明:

    -d datestr : 显示 datestr 中所设定的时间 (非系统时间)
    --help : 显示辅助讯息
    -s datestr : 将系统时间设为 datestr 中所设定的时间
    -u : 显示目前的格林威治时间
    --version : 显示版本编号

在这里插入图片描述

根据系统时间获取今年还剩下多少星期,已经过了多少星期
在这里插入图片描述
判定nginx进程是否存在,若不存在则自动拉起该进程

#!/bin/bash

nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)

if [ $nginx_process_num -eq 0 ];then
	systemctl start nginx
fi

在这里插入图片描述

4.4 有类型变量

declare和typeset命令

  • declare命令和typeset命令两者等价
  • declare、typeset命令都是用来定义变量类型的

declare命令参数表

参数含义
-r将变量设为只读
-i将变量设为整数
-a将变量定义为数组
-f显示此脚本前定义过的所有函数及内容
-F仅显示此脚本前定义过的函数名
-x将变量声明为环境变量

在这里插入图片描述

输出数组内容:
echo $array[@]}   输出全部内容
echo ${array[1]}  输出下标索引为1的内容

获取数组长度:
echo ${#array}    数组内元素个数
echo ${#array[2]} 数组内下标索引为2的元素长度

给数组某个下标赋值:
array[0]="lily"    给数组下标索引为1的元素赋值为lily
array[20]="hanmeimei"  在数组尾部添加一个新元素

删除元素:
unset array[2] 清除元素
unset array    清空整个数组

分片访问:
${array[@]:1:4} 显示数组下标索引从1开始到3的3个元素,不显内容替换:
${array[@]/an/AN}将数组中所有元素内包含an的子串替换为AN

数组遍历:
for v in ${array[@]}
do 
	echo $v 
done
  • 1

在这里插入图片描述

4.5 bash数学运算

4.5.1 bash数学运算之expr

语法格式
方法一   expr $numl operator $num2
方法二   $(($num1 operator $num2))
  •  

expr操作符对照表

操作符含义
num1|num2num1不为空且非0,返回num1;否则返回num2
num1&num2num1不为空且非0,返回num1;否则返回0
num1<num2num1小于num2,返回1;否则返回0
num1<=num2num1小于等于num2,返回1;否则返回0
num1=num2num1等于num2,返回1;否则返回0
num1!=num2num1不等于num2,返回1;否则返回0
num1>num2num1大于num2,返回1;否则返回0
num1>=num2num1大于等于num2,返回1;否则返回0
num1+num2求和
num1-num2求差
num1*hum2求积
num1/num2求商
num1%num2求余
在使用的时候需要进行转义
expr $numl \| $num2
expr $numl \& $num2
expr $numl \< $num2
expr $num1 \< $num2r
expr $numl \<=$num2
expr $num1 \>$num2
expr $numl \>=$num2
  •  

练习例子

提示用户输入一个正整数num,然后计算1+2+3+…+num的值;必须对num是否为正整数做判断,不符合应当再次允许输入

    #!/bin/bash
    #

    while true
    do
    	read -p "pls input a positive number: " num

    	expr $num + 1 &> /dev/null

    	if [ $? -eq 0 ];then
    		if [ `expr $num \> 0` -eq 1 ];then
    			for((i=1;i<=$num;i++))
    			do
    				sum=`expr $sum + $i`
    			done	
    			echo "1+2+3+....+$num = $sum"
    			exit
    		fi
    	fi
    	echo "error,input enlegal"
    	continue
    done

在这里插入图片描述

4.5.2 bash数学运算之bc

bc介绍

  • bc是bash内建的运算器,支持浮点数运算
  • 内建变量scale可以设置,默认为0

bc操作符对照表

操作符含义
num1+num2求和
num1-num2求差
num1*num2求积
num1/num2求商
num1%num2求余
num1^num2指数运算

在这里插入图片描述在这里插入图片描述

五. 函数的高级用法

5.1 函数定义和使用

函数介绍

  • Linux Shell中的函数和大多数编程语言中的函数一样
  • 将相似的任务或代码封装到函数中,供其他地方调用

语法格式

第一种格式
name()
{
	command1
	command2
	......
	commandn
}

第二种格式
function name
{
	command1
	command2
	......
	commandn
}
  •  

如何调用函数

 - 直接使用函数名调用,可以将其想象成Shell中的一条命令
 - 函数内部可以直接使用参数$1、$2...$n
 - 调用函数:function name $1 $2

实例

需求描述:写一个监控nginx的脚本;如果Nginx服务宕掉,则该脚本可以检测到并将进程启动,如果正常运行,则不做任何处理

#!/bin/bash

this_pid=$$

while true
do
ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null

if [ $? -eq 0 ];then
	echo "Nginx is running well"
	sleep 3
else
	systemctl start nginx
	echo "Nginx is down,Start it...."
fi
done

在这里插入图片描述

5.2 向函数传递参数

function name
{
	echo "Hello $1"
	echo "Hello $2"
}

函数调用:
name Lily Allen

实例
需求描述:
写一个脚本,该脚本可以实现计算器的功能,可以进行+ - * / 四种计算。

#!/bin/bash 	

function calcu

{

	case $2 in

		+)

			echo "`expr $1 + $3`"

			;;

		-)

			echo "`expr $1 - $3`"

			;;

		\\*)

			echo "`expr $1 \* $3`"

			;;

		/)

			echo "`expr $1 / $3`"

			;;

	esac

}

calcu $1 $2 $3

在这里插入图片描述

5.3 函数返回值

返回值的方式

方法一: 	
	return
	
方法二: 	
	echo
  •  

使用return返回值

  • 使用return返回值,只能返回1-255的整数
  • 函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败

实例

#!/bin/bash	
this_pid=$$



function is_nginx_running

{

	ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null

	if [ $? -eq 0 ];then

		return

	else

		return 1

	fi

}



is_nginx_running && echo "Nginx is running" || echo "Nginx is stoped"

  •  

在这里插入图片描述
使用echo返回值

  • 使用echo可以返回任何字符串结果
  • 通常用于返回数据,比如一个字符串值或者列表值
cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

    -b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
    -c :以字符为单位进行分割。
    -d :自定义分隔符,默认为制表符。
    -f :与-d一起使用,指定显示哪个区域。
    -n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的范围之内,该字符将被写出;否则,该字符将被排除
  •  
#!/bin/bash	
function get_users
{

	users=`cat /etc/passwd | cut -d: -f1`

	echo $users

}



user_list=`get_users`



index=1

for u in $user_list

do

	echo "The $index user is : $u"

	index=$(($index+1))

done

  •  

在这里插入图片描述

5.4 局部变量和全局变量

全局变量

  • 不做特殊声明,Shell中变量都是全局变量
  • Tips:大型脚本程序中函数中慎用全局变量

局部变量

  • 定义变量时,使用local关键字
  • 函数内和外若存在同名变量,则函数内部变量覆盖外部变量
#!/bin/bash	
var1="Hello world"


function test

{

	var2=87

}


echo $var1
echo $var2

test

echo $var1
echo $var2
  •  

在这里插入图片描述

#!/bin/bash	
var1="Hello world"


function test

{

	local var2=87

}


test



echo $var1
echo $var2

  •  

在这里插入图片描述

5.5 函数库

为什么要定义函数库

  • 经常使用的重复代码封装成函数文件
  • 一般不直接执行,而是由其他脚本调用

实例
定义一个函数库,该函数库实现以下几个函数
1、加法函数 add
2、减法函数 reduce
3、乘法函数 multiple
4、除法函数 divide
5、打印系统运行情况的函数sys_load,该函数可以显示内存情况


base_function
function add
{
	echo "`expr $1 + $2`"
}

function reduce
{
	echo "`expr $1 - $2`"
}

function multiple
{
	echo "`expr $1 \* $2`"
}

function divide
{
	echo "`expr $1 / $2`"
}

function sys_load
{
	echo "Memory Info"
	echo
	free -m
	echo
	echo "Disk Usage"
	echo
	df -h
	echo
}


test1.sh

#! /bin/bash
. /root/base_function

add 12 23

reduce 90 30

multiple 12 12

divide 12 2

sys_load


  • 1

在这里插入图片描述
总结

  • 库文件的后缀是任意的,但一般使用.lib
  • 库文件通常没有可执行选项
  • 库文件无需和脚本在同级目录,只需在脚本中引用时指定
  • 第一行一般使用#!/bin/echo,输出警告信息,避免用户执行

六. 文件查找

6.1 find命令

语法格式

find [路径] [选项] [操作]
  • 1

选项参数对照表

选项含义
-name根据文件名查找
-perm根据文件权限查找
-prune通常和-path一起使用,用于将特定目录排除在搜索条件之外 该选项可以排除某些查找目录
-user根据文件属主查找
-group根据文件属组查找
-mtime根据文件更改时间查找
-nogroup查找无有效属组的文件
-nouser查找无有效属主的文件
-newer file1 !file2查找更改时间比file1新但比file2旧IDE文件
-type按文件类型查找
-size按文件大小查找
-mindepth n从n级子目录开始搜索
-maxdepth n最多搜索到n级子目录
-exec对搜索到的文件执行特定的操作,格式为-exec command {} \;

注:
1、{} 和 \ 之间有空格
2、\ 和 ; 之间没有空格!

实例

-type
	f 文件 find . -type f
	d 目录 find . -type d
	c 字符设备文件 find . -type c
	b 块设备文件 find . -type b
	l 链接文件 find . -type l
	p 管道文件 find .-type p	

目录下以conf结尾的文件 
find /etc -name '*conf'   #-name不区分大小写

查找当前目录下文件名为aa的文件,不区分大小写
find . -iname aa

查找文件属主为hdfs的所有文件 
find . -user hdfs

查找文件属组为yarn的所有文件 
find . -group yarn

查找/etc目录下小于10000字节的文件
find /etc -size -10000c

查找/etc目录下大于1M的文件
find /etc -size +1M

-mtime 
	-n n天以内修改的文件 
	+n n天以外修改的文件
	n 正好n天修改的文件

查找/etc目录下5天之内修改且以conf结尾的文件
find /etc -mtime -5 -name1 '*.conf'

查找/etc目录下10天之前修改且属主为root的文件 
find /etc -mtime +10 -user root

查找/etc目录下30分钟之前修改的文件
find /etc -mmin +30

查找/etc目录下30分钟之内修改的目录
find /etc -mmin -30 -type d

在/etc下的3级子目录开始搜索
find /etc -mindepth 3

在/etc下搜索符合条件的文件,但最多搜索到2级子目录
find  /etc   -maxdepth 2 -type f -name '*.conf'

查找没有属主的用户
find . -type f -nouser

查找没有属组的用户
find .-type f -nogroup

-perm例子:
find.-perm 664

查找当前目录下所有普通文件,但排除test目录
find . -path ./etc -prune -o -type f

查找当前目录下所有普通文件,但排除etc和opt目录
find . -path . /etc -prune -o -path ./opt -prune -o -type f

查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs 
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs

查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs,且文件大小必须大于500字节
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs -a -size +500c

搜索/etc下的文件(非目录),文件名以conf结尾,且大于10k,然后将其删除
find . /etc/ -type f -name '*.conf' -size +10k -exec rm -f {} \;

将/var/1og/目录下以1og结尾的文件,且更改时间在7天以上的删除
find /var/log/ -name '*.log' -mtime +7 -exec rm -rf{} \;

搜索/etc下的文件(非目录),文件名以conf结尾,且大于10k,将其复制到/root/conf目录下
find . /etc/ -size +10k -type f -name '*.conf' -exec cp {} /root/conf/ \;

-ok 和exec功能一样,只是每次操作都会给用户提示

逻辑运算符:
-a      与
-o      或
-not | !  非

查找当前目录下,属主不是hdfs的所有文件
find . -not -user hdfs | find . ! -user hdfs

查找当前目录下,属主属于hdfs,且大小大于300字节的文件
find . -type f -a -user hdfs -a -size +300c

查找当前目录下的属主为hdfs或者以xm1结尾的普通文件
find . -type f -a \( -user hdfs -o -name '*.xml' \)
  •  

6.2 find、locate、whereis和which总结及适用场景分析

locate命令

  • 文件查找命令,所属软件包mlocate

  • 不同于find命令是在整块磁盘中搜索,locate命令在数据库文件中查找

  • find是默认全部匹配,locate则是默认部分匹配

updatedb命令

  • 用户更新/var/lib/mlocate/mlocate.db

  • 所使用配置文件/etc/updatedb.conf

  • 该命令在后台cron计划任务中定期执行

whereis命令

选项含义
-b只返回二进制文件
-m只返回帮助文档文件
-s只返回源代码文件

which命令
仅查找二进制程序文件

选项含义
-b只返回二进制文件

各命令使用场景推荐

命令适用场景优缺点
find查找某一类文件,比如文件名部分一致功能强大,速度慢
locate只能查找单个文件功能单一,速度快
whereis查找程序的可执行文件、帮助文档等不常用
which只查找程序的可执行文件常用于查找程序的绝对路径

七. 文件处理三剑客之grep

7.1 grep命令

grep 命令用于查找文件里符合条件的字符串。

7.1.1 语法格式

语法1:
grep [option] [ pattern] [file1, file2..]
语法2:
command | grep [option] [pattern]

在这里插入图片描述

7.1.2 grep参数

选项含义
-v不显示匹配行信息
-i搜索时忽略大小写
-n显示行号
-r递归搜索
-E支持扩展正则表达式
-F不按正则表达式匹配,按照字符串字面意思匹配
-c只显示匹配行总数
-w匹配整词
-x匹配整行
-l只显示文件名,不显示内容
-s不显示错误信息

在这里插入图片描述

7.1.3 grep和egrep

  • grep默认不支持扩展正则表达式,只支持基础正则表达式
  • 使用grep-E可以支持扩展正则表达式使用
  • egrep可以支持扩展正则表达式,与grep-E等价
    在这里插入图片描述

7.2 文件处理三剑客之sed

7.2.1 sed工作模式

sed(Stream Editor),流编辑器。对标准输出或文件逐行进行处理

语法格式

语法一:
stdout |sed [option] "pattern command"

语法二:
sed [option] "pattern command" file

7.2.2 sed选项

选项含义
-n只打印模式匹配行
-e直接在命令行进行sed编辑,默认选项
-f编辑动作保存在文件中,指定文件执行
-r支持扩展正则表达式
-i直接修改文件内容

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

edit.sed文件写入:

/python/p
  • 1

在这里插入图片描述

7.2.3 sed中的pattern详解

pattern用法表

匹配模式含义
10command匹配到第10行
10,20command匹配从第10行开始,到第20行结束10,
10,+5command匹配从第10行开始,到第16行结束
/pattern1/command匹配到pattern1的行
/pattern1/,/pattern2/command匹配到pattern1的行开始,到匹配到patern2的行结束
10,/pattern1/command匹配从第10行开始,到匹配到pettern1的行结束
/pattern1/,10command匹配到pattern1的行开始,到第10行匹配结束

实例

打印file文件的第17行
sed -n "17p" file

打印文件的10到20行
sed -n "10,20p" file

打印file文件中从第10行开始,往后面加5行
sed -n "10,+5p" file

打印file文件中以root开头的行
sed -n "/^root/p" file

打印file文件中第一个匹配到以ftp开头的行,到mail开头的行结束
sed -n "/^ftp/,/^mail/p" file

打印file文件中从第4行开始匹配,直到以hdfs开头的行结束
sed -n "4,/^hdfs/p" file

打印file文件中匹配root的行,直到第10行结束
sed -n "/root/,10p"file

7.2.4 sed中的编辑命令详解

编辑命令对照表

类别编辑命令含义
查询p打印
=只显示行号
增加a行后追加
i行前追加
r外部文件读入,行后追加
w匹配行写入外部文件
删除d删除
修改s/old/new将行内第一个old替换为new
s/old/new/g将行内全部的old替换为new
s/old/new/2g将行内从第2个old开始到剩下所有的old替换为new
s/old/new/ig将行内全部的old替换为new,忽略大小写

实例
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7.2.5 反向引用

先看一下例子

在这里插入图片描述
&和\1引用模式匹配到的整个串
两者区别在于只能表示匹配到的完整字符串,只能引用整个字符串;而\1可以使用()匹配到的字符

sed中引用变量时注意事项:
(1)、匹配模式中存在变量,则建议使用双引号
(2)、sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号

#!/bin/bash

old_str=hadoop
new_str=HADOOP

sed -i "s/$old_str"/"$new_str/g" abc.txt
  •  

在这里插入图片描述

7.2.6 利用sed查找文件内容

需求描述:
处理一个类似MySQL配置文件my.cnf的文本,示例如下;编写脚本实现以下功能:输出文件有几个段,并且针对每个段可以统计配置参数总个数

my.cnf

# this is read by the standalone daemon and embedded servers
[client]
port=3306
socket=/tmp/mysql.socket

#ThisSegmentForserver
[server]
innodb_buffer_pool_size=91750M
innodb_buffer_pool_instances=8
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
innodb_data_file_path=ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=2G
innodb_log_files_in_group=2
innodb_max_undo_log_size=4G
innodb_undo_directory=undolog
innodb_undo_tablespaces=95

#thisisonlyforthemysqldstandalonedaemon
[mysqld]
port=3306
socket=/tmp/mysql.sock
basedir=/usr/local/mysql
datadir=/data/mysql
pid-file=/data/mysql/mysql.pid
user=mysql
bind-address=0.0.0.0
sort_buffer_size=16M
join_buffer_size=16M
thread_cache_size=3000
interactive_timeout=600
wait_timeout=600

#ThisSegmentFormysqld_safe
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
max_connections=1000
open_files_limit=65535
thread_stack=512K
external-locking=FALSE
max_allowed_packet=32M

#thisisonlyforembeddedserver
[embedded]
gtid_mode=on
enforce_gtid_consistency=1
log_slave_updates
slave-rows-search-algorithms='INDEX_SCAN,HASH_SCAN'
binlog_format=row
binlog_checksum=1
relay_log_recovery=1
relay-log-purge=1


#usethisgroupforoptionsthatolderserversdon'tunderstand
[mysqld-5.5]
key_buffer_size=32M
read_buffer_size=8M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
myisam_sort_buffer_size=128M
myisam_max_sort_file_size=10G
myisam_repair_threads=1
lock_wait_timeout=3600
explicit_defaults_for_timestamp=1
innodb_file_per_table=1

预想输出结果:
1:client 2
2:server 12
3:mysqld 12
4:mysqld_safe 7
5:embedded 8
6:mysqld-5.5 10

脚本

#!/bin/bash

FILE_NAME=/root/Desktop/dir2/my.cnf

function get_all_segments
{
	echo "`sed -n '/\[.*\]/p' $FILE_NAME |sed -e 's/\[//g' -e 's/\]//g'`"
}



function count_items_in_segment
{
	
	echo "`sed -n '/\['$1'\]/,/\[.*\]/p' $FILE_NAME  | grep -v ^# |grep -v ^$ |grep -v "\[.*\]" |wc -l `"
}

num=0
for seg in `get_all_segments`
do
	num=`expr $num + 1`
	items_count=`count_items_in_segment $seg`
	echo "$num:$seg  $items_count"
done

  •  

在这里插入图片描述

7.2.7 利用sed删除文件内容

删除配置文件中的所有注释行和空行
sed -i '/[:blank:]*#/d;/^$/d' nginx.conf

在配置文件中所有不以#开头的行前面添加*符号,注意:以#开头的行不添加
sed -i 's/^[^#]/\*&/g' nginx.conf

7.2.8 利用sed修改文件内容

修改用法总结:

1、1s/old/new/

2、5,10s/old/new/

3、10,+10s/old/new/

4、/pattern1/s/old/new/

5、/pattern1/,/pattern2/s/old/new/

6、/pattern1/,20s/old/new/

7、15,/pattern1/s/old/new/
  • 1

 

修改/etc/passwd中第1行中第1个root为ROOT	
sed -i '1s/root/ROOT/' passwd

修改/etc/passwd中第5行到第10行中所有的/sbin/nologin为/bin/bash
sed -i '5,10s/\/sbin\/nologin/\/bin\/bash/g' passwd

修改/etc/passwd中匹配到/sbin/nologin的行,将匹配到行中的login改为大写的LOGIN
sed -i '/\/sbin\/nologin/s/login/LOGIN/g' passwd

修改/etc/passwd中从匹配到以root开头的行,到匹配到行中包含mail的所有行。修改内为将这些所有匹配到的行中的bin改为HADOOP
sed -i '/^root/,/mail/s/bin/HADOOP/g' passwd

修改/etc/passwd中从匹配到以root开头的行,到第15行中的所有行,修改内容为将这些行中的nologin修改为SPARK
sed -i '/^root/,15s/nologin/SPARK/g' passwd

修改/etc/passwd中从第15行开始,到匹配到以yarn开头的所有航,修改内容为将这些行中的bin换位BIN
sed -i '15,/^yarn/s/bin/BIN/g' passwd

  •  

7.2.9 利用sed追加文件内容

1、a					在匹配行后面追加		
2、i					在匹配行前面追加
3、r					将文件内容追加到匹配行后面
4、w					将匹配行写入指定文件	
  •  

实例

1、a	append
		
(1)、passwd文件第10行后面追加"Add Line Behind"		
sed -i '10a Add Line Begind' passwd
(2)、passwd文件第10行到第20行,每一行后面都追加"Test Line Behind"
sed -i '10,20a Test Line Behind' passwd
(3)、passwd文件匹配到/bin/bash的行后面追加"Insert Line For /bin/bash Behind"
sed -i '/\/bin\/bash/a Insert Line For /bin/bash Behind' passwd
		
2、i
		
(1)、passwd文件匹配到以yarn开头的行,在匹配行前面追加"Add Line Before"
sed -i '/^yarn/i Add Line Before' passwd
(2)、passwd文件每一行前面都追加"Insert Line Before Every Line"
sed -i 'i Insert Line Before Every Line' passwd
			
3、r
		
(1)、将/etc/fstab文件的内容追加到passwd文件的第20行后面
sed -i '20r /etc/fstab' passwd
(2)、将/etc/inittab文件内容追加到passwd文件匹配/bin/bash行的后面
sed -i '/\/bin\/bash/r /etc/inittab' passwd
(3)、将/etc/vconsole.conf文件内容追加到passwd文件中特定行后面,匹配以ftp开头的行,到第18行的所有行
sed -i '//,18r /etc/vconsole.conf' passwd
			
4、w
		
(1)、将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中
sed -i '/\/bin\/bash/w /tmp/sed.txt' passwd
(2)、将passwd文件从第10行开始,到匹配到hdfs开头的所有行内容追加到/tmp/sed-1.txt
sed -i '10,/^hdfs/w /tmp/sed-1.txt' passwd
				

7.3 文本处理三剑客之awk

7.3.1 awk工作模式

awk是一个文本处理工具,通常用于处理数据并生成结果报告

awk 'BEGIN{} pattern{commands}END{}' file_name
standard output | awk 'BEGIN{}pattern{commands}END{}'
  • 1
  • 2

语法格式说明

语法格式解释
BEGIN{}正式处理数据之前执行
pattern匹配模式
{commands}处理命令,可能多行
END{}处理完所有匹配数据后执行

7.3.2 awk内置变量

内置变量含义
$0打印行所有信息
$1~$n打印行的第1到n个字段的信息
NFNumber Field 处理行的字段个数
NRNumber Row 处理行的行号,从1开始计数
FNRFile Number Row 多文件处理时,每个文件单独记录行号,都是从0康凯斯
FSField Separator 字段分割符,不指定时默认以空格或tab键分割
RSRow Separator 行分隔符,不指定时以回车分割\n
OFSOutput Filed Separator 输出字段分隔符。
ORSOutput Row Separator 输出行分隔符
FILENAME处理文件的文件名
ARGC命令行参数个数
ARGV命令行参数数组

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.3.3 awk格式化输出之printf

格式符

格式符含义
%s打印字符串
%d打印10进制数
%f打印浮点数
%x打印16进制数
%o打印8进制数
%e打印数字的科学计数法格式
%c打印单个字符的ASCII码
修饰符含义
-左对齐
+右对齐
#显示8进制在前面加o,显示16进制在前面加0x

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实例

1、以字符串格式打印/etc/passwd中的第7个字段,以":"作为分隔符
			
awk 'BEGIN{FS=":"} {printf "%s\n",$7}' /etc/passwd
			
2、以10进制格式打印/etc/passwd中的第3个字段,以":"作为分隔符
			
awk 'BEGIN{FS=":"} {printf "%d\n",$3}' /etc/passwd
			
3、以浮点数格式打印/etc/passwd中的第3个字段,以":"作为分隔符
			
awk 'BEGIN{FS=":"} {printf "%0.3f\n",$3}' /etc/passwd
			
4、以16进制数格式打印/etc/passwd中的第3个字段,以":"作为分隔符
			
awk 'BEGIN{FS=":"} {printf "%#x\n",$3}' /etc/passwd
			
5、以8进制数格式打印/etc/passwd中的第3个字段,以":"作为分隔符
			
awk 'BEGIN{FS=":"} {printf "%#o\n",$3}' /etc/passwd
			
6、以科学计数法格式打印/etc/passwd中的第3个字段,以":"作为分隔符
			
awk 'BEGIN{FS=":"} {printf "%e\n",$3}' /etc/passwd
  •  

7.3.4 awk模式匹配的两种用法

第一种
RegExp  按正则表达式匹配
第二种
关系运算匹配  按关系运算匹配

RegExp

匹配/etc/passwd文件行中含有root字符串的所有行

awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd
  • 1

匹配/etc/passwd文件行中以yarn开头的所有行

awk 'BEGIN{FS=":"}/^yarn/{print $0}' /etc/passwd
  • 1

运算符匹配

<			小于

>			大于

<=			小于等于

>=			大于等于

==			等于

!=			不等于

~			匹配正则表达式

!~			不匹配正则表达式
  •  

实例

以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息

awk 'BEGIN{FS=":"}$3<50{print $0}' /etc/passwd

以:为分隔符,匹配/etc/passwd文件中第3个字段大于50的所有行信息

awk 'BEGIN{FS=":"}$3>50{print $0}' /etc/passwd
以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息

awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd

以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息

awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' /etc/passwd

以:为分隔符,匹配/etc/passwd中第3个字段包含3个以上数字的所有行信息

awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{print $0}' /etc/passwd


  •  

布尔运算符匹配:

||		或

&&		与

!		非

实例

以:为分隔符,匹配/etc/passwd文件中包含hdfs或yarn的所有行信息

awk 'BEGIN{FS=":"}$1=="hdfs" || $1=="yarn" {print $0}' /etc/passwd

以:为分隔符,匹配/etc/passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息

awk 'BEGIN{FS=":"}$3<50 && $4>50 {print $0}' /etc/passwd

7.3.5 awk表达式用法

运算符含义
+
/
%
^或**乘方
++x在返回x变量之前,×变量加1
X++在返回x变量之后,×变量加1

实例

使用awk计算/etc/services中的空白行数量

awk '/^$/{sum++}END{print sum}' /etc/services
  • 1

计算学生课程分数平均值,学生课程文件内容如下:
Allen 80 90 96 98
Mike 93 98 92 91
Zhang 78 76 87 92
Jerry 86 89 68 92
Han 85 95 75 90
Li 78 88 98 100

awk '{total=$2+$3+$4+$4;AVG=total/4;printf "%-8s%5d%5d%5d%5d%0.2f\n",$1,$2,$3,$4,$5,AVG}' student.txt
  • 1

在这里插入图片描述

7.3.6 awk动作中的条件及循环语句

条件语句:

if(条件表达式1)
	动作
else if(条件表达式2)
	动作
else
	动作

以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行信息

awk 'BEGIN{FS=":"}{if($3<50){ printf "%-20s%-20s%-5d\n","小于50的UID",$1,$3} else if($3>100) {printf "%-20s%-20s%-5d\n","大 于100的UID",$1,$3} else{ printf "%-20s%-20s%-5d\n","大于50 小于100的UID",$1,$3}}' /etc/passwd

  • 1
  • 2

在这里插入图片描述
循环语句:

while循环:

while(条件表达式)
	动作
					
do while循环:
	do
		动作
	while(条件表达式)
				
for循环:
	for(初始化计数器;计数器测试;计数器变更)
		动作

实例:

计算1+2+3+4+…+100的和,请使用while、do while、for三种循环方式实现

while

BEGIN{
	while(i<=100) #不需要事先声明
	{
		sum+=i
		i++
	}
	print sum
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

for

BEGIN{
	for(i=0;i<=100;i++) #不需要事先声明
	{
		sum+=i
	}
	print sum
}

do while

BEGIN{
	do
	{
		sum+=i
		i++
	}while(i<=100)
	print sum
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

7.3.7 awk中的字符串函数

函数名解释
length(str)计算长度
index(str1,str2)返回在str1中查询到的str2的位置
tolower(str)小写转换
toupper(str)大写转换
split(str,arr,fs)分隔字符串,并保存到数组中
match(str,RE)返回正则表达式匹配到的子串的位置
substr(str,m,n)截取子串,从m个字符开始,截取n位。n若不指定,则默认截取到字符串尾
sub(RE,RepStr,str)替换查找到的第一个子串
gsub(RE,RepStr,str)替换查找到的所有子串

以:为分隔符,返回/etc/passwd中每行中每个字段的长度

root: x:0:0:root:/root:/bin/bash
4:1:1:1:4:5:9

BEGIN{
	FS=":"
	
}
{
	i=0
	while(i<=NF)
	{
		if(i==NF)
			printf "%d",length($i)	
		else
			printf "%d:",length($i)
		i++

	}
	print ""

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述
搜索字符串"I have a dream"中出现"ea"子串的位置
awk 'BEGIN{str=“I hava a dream”;location=index(str,“ea”);print location}

awk ‘BEGIN{str=“I hava a dream”;location=match(str,“ea”);print location}’

将字符串"Hadoop is a bigdata Framawork"全部转换为小写
awk ‘BEGIN{str=“Hadoop is a bigdata Framework”;print tolower(str)}’

将字符串"Hadoop is a bigdata Framawork"全部转换为大写
awk ‘BEGIN{str=“Hadoop is a bigdata Framework”;print toupper(str)}’

将字符串"Hadoop Kafka Spark Storm HDFS YARN Zookeeper",按照空格为分隔符,分隔每部分保存到数组array中
awk ‘BEGIN{str=“Hadoop Kafka Spark Storm HDFS YARN Zookeeper”;split(str,arr," ");for(a in arr) print arr[a]}’

搜索字符串"Tranction 2345 Start:Select * from master"第一个数字出现的位置
awk ‘BEGIN{str=“Tranction 2345 Start:Select * from master”;location=match(str,/[0-9]/);print location}’

截取字符串"transaction start"的子串,截取条件从第4个字符开始,截取5位

awk ‘BEGIN{str=“transaction start”;print substr(str,4,5)}’

替换字符串"Tranction 243 Start,Event ID:9002"中第一个匹配到的数字串为$符号

awk ‘BEGIN{str=“Tranction 243 Start,Event ID:9002”;count=sub(/[0-9]+/,"$",str);print count,str}’

awk ‘BEGIN{str=“Tranction 243 Start,Event ID:9002”;count=gsub(/[0-9]+/,"$",str);print count,str}’

7.3.8 awk的常用选项

选项解释
-v参数传递
-f指定脚本文件
-F指定分隔符
-V查看awk的版本号

在这里插入图片描述

7.3.9 awk中数组的用法

shell中数组的用法:

打印元素:
echo ${array[2]}

打印元素个数:
echo ${#array[@]}

打印元素长度:
echo ${#array[3]}

给元素赋值:
array[3]="Li"

删除元素:
unset array[2];unset array

分片访问:
echo ${array[@]:1:3}

元素内容替换:
${array[@]/e/E}只替换第一个e;
$tarray[@]//e/E}替换所有的e

数组的遍历:
for a in array 
do
	echo $a 
done 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这里插入图片描述
在这里插入图片描述

awk中数组的用法

在awk中,使用数组时,不仅可以使用1.2…n作为数组下标,也可以使用字符串作为数组下标

当使用1.2.3…n时,直接使用array[2]访问元素;需要遍历数组时,使用以下形式:

str="Allen Jerry Mike Tracy Jordan Kobe Garnet"
split(str,array," ")
for(i=1;i<length(array);i++)
	print array[i]
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
当使用字符串作为数组下标时,需要使用array[str]形式访问元素;遍历数组时,使用以下形式:

array["var1"]="Jin"
array["var2"]="Hao"
array["var3"]="Fang"
for(a in array)
	print array[a]
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

7.3.10 实例

  1. 统计主机上所有的TCP连接状态数,按照每个TCP状态分类
netstat -an | grep tcp | awk '{array[$6]++} END{for(a in array) print a,array[a]}'
  • 1

在这里插入图片描述
2. 计算横向数据总和,纵向数据总和
allen 80 90 87 91
mike 78 86 93 96
Kobe 66 92 82 78
Jerry 98 74 66 54
Wang 87 21 100 43

BEGIN{ 
	printf "%-10s%-10s%-10s%-10s%-10s%-10s\n","Name","Yuwen","Math","English","Physical","Total"
}
{
	total=$2+$3+$4+$5
	yuwen_sum+=$2
	math_sum+=$3
	english_sum+=$4
	physical_sum+=$5
	printf "%-10s%-10d%-10d%-10d%-10d%-10d\n",$1,$2,$3,$4,$5,total
}
END{
	printf "%-10s%-10d%-10d%-10d%-10d\n","total",yuwen_sum,math_sum,english_sum,physical_sum
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值