shell脚本学习

4 篇文章 1 订阅

一、学习资源

1.1 入门学习

        菜鸟教程:Shell 教程 | 菜鸟教程

        快速入门:https://www.jb51.net/article/161028.htm

        常用命令:Shell 常用命令 - 徐锅 - 博客园

1.2 实战练习

        牛客网题库

        参考:Shell实战题库_面试必刷+解析_牛客题霸_牛客网

        脚本练习实例

        shell脚本编程进阶总结 - 千纸赫H - 博客园

        shell脚本日常练习

        shell脚本基础日常练习_Random_code的博客-CSDN博客_shell 脚本练习

二、主要内容

2.1 命令

awk命令详解

        参考:Shell脚本之awk篇 - 我若亦如风 - 博客园

        与grep命令的配合使用:

        示例:(判断boot分区可用容量小于20M时报警,否则显示OK)

df | grep "boot" | awk '{if($4<20000) print "Alart"; else print "OK"}'

basename命令

        博客:Shell basename命令_DreamWendy-CSDN博客

command命令

        博客:Shell command命令_DreamWendy-CSDN博客

echo命令详解

        参考:Shell echo命令 | 菜鸟教程

export命令详解

        参考:shell与export命令 - tooltime - 博客园

expr命令详解

        参考:SHELL脚本--expr命令全解 - 骏马金龙 - 博客园

grep命令详解

        博客:Shell grep命令_DreamWendy-CSDN博客

let命令的用法

        在shell中,let命令用于指定算术运算,即 let expretion,示例代码如下:

#!/usr/bin/env bash
## 运行结果:
## a init is 2
## a+=1 is 3
a=2
echo "a init is $a"
let "a+=1"
echo "a+=1 is $a"

local命令的作用

        作用:一般用于shell内局部变量的定义,多使用在函数内部

        关于局部变量和全局变量(主要理解第3点):
        (1)shell 脚本中定义的变量是global的,作用域从被定义的地方开始,一直到shell结束或者被显示删除的地方为止。
        (2)shell函数定义的变量也是global的,其作用域从 函数被调用执行变量的地方 开始,到shell或结束或者显示删除为止。函数定义的变量可以是local的,其作用域局限于函数内部。但是函数的参数是local的。
        (3)如果局部变量和全局变量名字相同,那么在这个函数内部,会使用局部变量。

        使用实例:

#!/bin/bash
text='global var'
function Hello() {
    local text='local var!!!'
    #局部变量 
	echo $text 
}
Hello

## 运行结果
$PC: ./local_com.sh
local var!!!

## 结果分析
调用Hello方法,进入后执行echo输出text变量;
当方法外部和内部都定义了同一个变量时,在函数内部优先输出local定义的局部变量

printf命令的使用

        printf 命令模仿 C 程序库(library)里的 printf() 程序。printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n

        格式:

printf format-string [arguments...]

        使用实例:

printf "hello shell\n"
printf "%-10s" read $1
printf "%-10s %-8s %-4.2f\n" LZS cool 48.6543 

        读取输入的一个参数并打印成字符串,%-10s 指一个宽度为 10 个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示 在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。 %-4.2f 指格式化为小数,其中.2 指保留 2 位小数;

        printf的转义序列:

        (1)\a—警告字符,通常为ASCII的BEL字符
        (2)\b—后退
        (3)\c—抑制(不显示)输出结果中任何结尾的换行字符(只在%b 格式指示符控制下的
参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任
何留在格式字符串中的字符,都被忽略
        (4)\f—换页
        (5)\n—换行
        (6)\r—回车
        (7)\t水平制表符
        (8)\v垂直制表符

        (9)\一个字面上的反斜杠字符
        (10)\ddd表示1到3位数的八进制字符,仅在格式字符串中有效
        (11)\0ddd表示1到3位的八进制字符

seq命令的用法

        参考:shell脚本之seq命令_灰灰的博客-CSDN博客

shift命令

        参考:Shell编程中Shift的用法 - image eye - 博客园

        位置参数可以用shift命令左移,比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1,$2,$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。

        我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当shell程序不知道其个数时可以把所有参数一起赋值给变量$*。当用户要求shell在不知道位置变量个数的情况下,还能逐个的把参数一一进行处理,也就是在$1后为$2等。在shift命令执行前变量$1的值在shift命令执行后就不可用了。

        shift命令测试实例:

#!/bin/bash
    until [ $# -eq 0 ];do
    echo "The first argument is:$1,The number of arguments is:$#"
    shift
    done

unset命令的用法

        unset命令使用规则:unset var

        unset可以删除变量,被删除后,变量不能再次被使用,如下代码:

#!/bin/bash
var="unset test"
unset var
echo $var

        该段代码将无任何输出,注意,unset不能删除只读变量,for循环等子代码块中的临时变量要及时使用unset删除;

2.2 语法

 case语句用法

        (1)";;"相当于其他语言的"break";

        (2)"*)"相当于其他语言的"default";

        (3)esac是case语句的结束;

        (4)"-)"、"d)"等相当于其他语言的"case '-': "、"case 'd': ";

括号的使用

        参考:shell中各种括号的作用()、(())、[]、[[]]、{}_乌托邦-CSDN博客

select循环

         (1)select是个无线循环,因此要记住用break命令退出循环,或用exit命令终止脚本。也可以按ctrl+c退出循环。

        (2)select经常和case联合使用。

        (3)与for循环类似,可以省略in list,此时使用位置变量。

        使用实例如下:

#!/bin/bash
#定义PS3提示符
PS3="Please choose the menu:"
#输出菜单
select menu in yangroutang mifan hulatang jiaozi lamian huimian quit
do
#   判断选择
    case $REPLY in
    1|4)
        echo "The price is 20"
        ;;
    2|5)
        echo "The price is 12"
        ;;
    3|6)
        echo "The price is 10"
        ;;
    7)
        break
        ;;
    *)
        echo "Choose error"
        ;;
    esac
done

2.3 正则表达式

        参考教程:正则表达式 – 语法 | 菜鸟教程

        Perl正则表达式(最常用的正则表达式)

        参考:Perl 正则表达式 | 菜鸟教程

2.4 符号

glob(通配符)详解

        参考:Shell之Glob和RE的区别 - ZakZhu - 博客园

 shell中$0等的含义

        参考:Shell脚本中$0、$?、$!、$$、$*、$#、$@等的意义以及linux命令执行返回值代表意义_helloxiaozhe的博客-CSDN博客

        $*和$@的用法:

        shell脚本中$* 和 $@ 区别_寰宇001的博客-CSDN博客_shell脚本$*

shell中 &>和2>&1的含义

         参考:Shell中 &>/dev/null和 >/dev/null 2>&1_weixin_34274029的博客-CSDN博客

        >、<、>>、<<的区别:

        >: 将标准输入以覆盖的方式写入文件;

        <: 将标准输出以覆盖的方式写入文件;

        >>: 将标准输入以追加的方式写入文件;

        <<: 将标准输出以追加的·方式写入文件;

shell中三种引号的用法及区别

        参考:https://www.jb51.net/article/108330.htm

shell中 ${}, ##, %%, :-,:+, ? 的使用

        参考:shell中 ${}, ##, %%, :-,:+, ? 的使用_XFH1207的博客-CSDN博客

shell 之 -f -z -e -o -a -d 等判断符

        参考:Shell 基本运算符 | 菜鸟教程

三、学习实例 

3.1 语法

1. 编写脚本,提示输入正整数n的值,计算1+2+…+n的总和。

#!/bin/bash
read -p "please input a positive integer:" n
i=1
sum=0
for i in ‘seq 1 $n’;do
   if [[ $n =~ (^[0-9]*[1-9][0-9]*$) ]];then  #判断n是否为正整数
       let sum+=i
   else
       echo "a wrong int" && exit
   fi
       let i++
done
echo "sum is $sum"

相关知识:

        (1)seq命令的用法,见本文 "seq命令的用法";

        (2)正则表达式,"=~"符号见本文 "Perl正则表达式",正则表达式见本文 "正则表达式";

        (3)let命令:见本文"let命令";

--------------------------------------------------------------------------------------------------------------------------------

2. 编写脚本/root/bin/yesorno.sh,提示用户输入yes或no, 并判断用户输入的是yes还是no,或是其它信息。

#!/bin/bash
read -p "can i help you? yes or no " ans
case $ans in
[yY][eE][sS]|[yY])
         echo "ok,come on"
         ;;
[nN][oO]|[nN])
         echo "no,thanks"
         ;;
*)
         echo "byebye"
         ;;
esac

相关知识:

        (1)"case"见本文"shell case语句用法"

        (2)"[yY][eE][sS]|[yY]"匹配 "yes" 或 "y",其中的三个字母可随意大小写;

---------------------------------------------------------------------------------------------------------------------------------

3. 编写脚本/root/bin/filetype.sh,判断用户输入文件路径 ,显示其文件类型(普通,目录,链接,其它文件类型)

#!/bin/bash
read -p "please input file path:" path
a='ls -l $path|grep -o "^."'   #脚本里面不能使用别名,所以用ls -l
case $a in
-)
 echo "common file"
 ;;
d)
 echo "directory file"
 ;;
l)
 echo "linked file"
 ;;
*)
 echo "other file"
 ;;
esac

相关知识:

        (1)ls -l表示以这样的格式列出所有文件:

                total 32
                drwxrwxr-x 2 xiao xiao 4096 Nov 17 10:16 count_lines
                -rwxrwxrwx 1 xiao xiao  392 Nov 18 10:38 create_user.sh

        (2)|表示管道,即前一个命令的结果给后一个命令做输入;

        (3)grep -o "^."表示根据前面列出的第一个参数"drwxrwxr-x",列出该文件的类型,^表示行首;

        (4)"-)"、"d)"等见本文"shell case语句用法"

--------------------------------------------------------------------------------------------------------------------------------

4. 在Shell中接收传入的参数有两种方式,一种是通过脚本进行参数传递,另外一种是通过read来接收传入的参数;

        通过脚本来传递参数的简单示例如下:

# 通过脚本来传递,这里$0指脚本名,$1为第一个参数,$2为第二个参数
[root@host ~]# ./script.sh 1 2
Total = 3
[root@host ~]# vim script.sh
#!/bin/bash
function add() {
  total=$(expr $1 + $2)
  echo -e "Total = $total"
}
add $1 $2

        再来看通过read来接收传入的参数,先看read的基本格式

read [-rs] [-a ARRAY] [-d delim] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [var1 var2 var3......]

        read使用实例

[root@host ~]# ./script.sh 
Enter Password:
The password your input is: Test@1234\
[root@host ~]# vim script.sh
#!/bin/bash
read -n10 -t30 -r -s -d $ -p "Enter Password:" password
echo -e "\nThe password your input is:$password"

        参数分析

        (1)-p 提示语句,后面接输入提示信息,这里为'Enter Password: '

        (2)-n 参数个数,有时候要限制密码长度,或者其他输入长度限制,比如[Y/N],只输入输入一位,-n1

        (3)-s 屏蔽回显,屏幕上不显示输入内容,一般用于密码输入

        (4)-t 等待时间,这里设置30秒,30秒内未输入或者输入不全,终止

        (5)-d 输入界限,这里是$,输入到$,自然终止输入

        (6)-r 屏蔽特殊字符\的转译功能,加了之后作为普通字符处理

相关知识:

        (1)expr命令,见本文"expr命令详解";

        (2)echo -e "-e"表示开启转义,见本文 "echo命令详解";

---------------------------------------------------------------------------------------------------------------------------------

5. 计算100以内所有能被3整除的整数之和;

#!/bin/bash
sum=0
i=1
for i in {1..100};do
    if [ $[$i%3] -eq 0 ];then
       let sum+=i
    fi
       let i++
done
echo $sum

 相关知识:

        (1)关注for循环 "{1..100}"表示从1到100;

        (2)关注 "$[$i%3]",当需要将计算的结果形成变量时,需要按该形式书写;

        (3)关于for,见本文"for循环列表生成方式";

---------------------------------------------------------------------------------------------------------------------------------

3.2 功能

1. 使用shell脚本检测局域网主机是否宕机;

#!/bin/bash
for i in {1..254}
    #-c指定ping几次,-i指定超时    
    ping -c 2 -i 0.5 192.168.43.$i  &> /dev/null
    #$?是上一个指令的执行返回值 ,0表示没有错误,其他任何值表明有错误
    #-eq equal 的缩写
    if [$? -eq 0]; then
        echo "192.168.43.$i is up"
    else
        echo "192.168.43.$i is down"
    fi
done 

2. 编写一个脚本,名为createscripts.sh ,当执行该脚本时,输入 createscripts.sh /path/newsh.sh 则会在指定路径生成脚本文件(涵盖注释信息),并且自动打开该文件,开始编辑,在编辑结束后,自动给该脚本加上执行权限。

#!/bin/bash
#
A=`basename $1 |grep -o "\.sh$"` 
#echo $A
if [ -n "$A" ];then
		echo -e "#!/bin/bash \n#" >> $1
		echo  "#---------------------------------------" >> $1
		echo  "# Filename:    `basename $1`" >> $1
		echo  "# Revision:    1.0" >> $1
		echo  "# Date:        `date +"%F %T"`">> $1
		echo  "# Author:      `id -nu`" >> $1
		echo  "# Email:       sezina_f@163.com" >> $1
		echo  "# Description:" >> $1
		echo  "#---------------------------------------" >> $1
		echo  "# Copyright:   2020 tzx" >> $1
		echo  "# License:     GPL" >> $1
		echo  >> $1
		vim +13 $1
		chmod +x $1
	else
		echo "Usage: Please end file with .sh."
fi

 相关知识:

        (1)反引号(``)的用法见本文 "符号 -> shell中三种引号的用法和区别";

        (2)basename主要用于去除去除文件名的目录部分和后缀部分,返回一个字符串参数的基本文件名称,具体用法见本文 "命令 -> basename命令" ;

        (3)grep -o:只匹配符合正则表达式中相应规则的字符串(即无空格等空白字符);

        (4)正则表达式中 "."表示 “匹配除换行符 \n 之外的任何单字符” ,这里是要匹配 ".sh",所以使用 "\."转义字符;

        (5)>>是将标准输出以追加的方式写入文件,具体含义见本文 "shell中 &>和2>&1的含义 -> '>、<、>>、<<的区别' " ;

        (6)vim +13 $1表示:创建该文件,并将光标定位到第13行让用户编辑(因为前12行已经有我们自动写入的内容了);

        (7)chmod +x表示:给该文件赋予可执行权限;

3. 编写脚本systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小;

#!/bin/bash
	echo "当前主机系统如下:"
	echo "主机名: $(hostname)"
	echo "IPV4地址: "  "$(ifconfig|grep "inet "|grep -o "\([0-9]\{1,3\}\.\)\{3\}[1-9]\{1,3\}")"
	echo "操作系统版本:" "$(cat /etc/redhat-release)"
	echo "内核版本:" "$(uname -r)"
	echo "CPU型号:" "$(lscpu|grep -i "model name")"
	echo "内存大小" $(free -hm|head -2|tr -s " "  |tail -1|cut -d" " -f2)
	echo "磁盘容量" $(fdisk -l /dev/sda|head -2|tail -1|cut -d " " -f3,4)

4. 编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利用率最大的值;

echo "当前硬盘分区中空间利用率最大的值:$( df |grep -o "[0-9]\{1,3\}%" |sort -rn |head -1)"

5. 编写脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和;

space1=`cat $1 |grep "^[[:space:]]*$"|wc -l`
space2=`cat $2 |grep "^[[:space:]]*$"|wc -l`
echo $space1+$space2 |bc

6. 任意用户登录系统时,显示红色字体的警示提醒信息“Hi,dangerous!”

vim /etc/profile.d/env.sh
echo -e '\033[31m hi,dangerous! \033[0m'

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值