shell 脚本编程基础篇

一级标题

二级标题

1.编程基础

Linus:Talk is cheap, show me the code

程序组成

程序:算法+数据结构

数据:是程序的核心

算法:处理数据的方式

数据结构:数据在计算机中的类型和组织方式

面向过程语言
 做一件事情,排出个步骤,第一步干什么,第二步干什么,如果出现情况A,做什么处理,如
 果出现了情况B,做什么处理
 问题规模小,可以步骤化,按部就班处理
 以指令为中心,数据服务于指令
 C,shell

面向对象语言
 一种认识世界、分析世界的方法论。将万事万物抽象为各种对象
 类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合
 对象是类的具象,是一个实体
 问题规模大,复杂系统
 以数据为中心,指令服务于数据
 java,C#,python,golang等

编程语言

  计算机:运行二进制指令

  编程语言:人与计算机之间交互的语言。分为两种:低级语言和高级语言

  低级编程语言:

   机器:二进制的0和1的序列,称为机器指令。与自然语言差异太大,难懂、难写

   汇编:用一些助记符号替代机器指令,称为汇编语言
   如:ADD A,B 将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中
   汇编语言写好的程序需要汇编程序转换成机器指令
   汇编语言稍微好理解,即机器指令对应的助记符,助记符更接近自然语言

  高级编程语言:
  编译:高级语言-->编译器-->机器代码文件-->执行,如:C,C++
  解释:高级语言-->执行-->解释器-->机器代码,如:shell,python,php,JavaScript,perl

编程逻辑处理方式
   顺序执行
   选择执行
   循环执行

二级标题

2.脚本基本格式

shell 脚本的用途

自动化常用命令

执行系统管理和故障排除

创建简单的应用程序

处理文本或文件

shell脚本基本结构

shell脚本编程:是基于过程式、解释执行的语言

编程语言的基本结构:

各种系统命令的组合

数据存储:变量、数组

表达式:a + b

控制语句:if

shell脚本:包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行shebang机制

 #!/bin/bash
 #!/usr/bin/python
 #!/usr/bin/perl

创建shell脚本过程

第一步:使用文本编辑器来创建文本文件

第一行必须包括shell声明序列:#!

!/bin/bash

添加注释,注释以#开头

第二步:加执行权限

给予执行权限,在命令行上指定脚本的绝对或相对路径

第三步:运行脚本

直接运行解释器,将脚本作为解释器程序的参数运行

脚本注释规范

1、第一行一般为调用使用的语言

2、程序名,避免更改文件名为无法找到正确的文件

3、版本号

4、更改后的时间

5、作者相关信息

6、该程序的作用,及注意事项

7、最后是各版本的更新简要说明

参考文档:

https://zh.wikipedia.org/wiki/Hello_World

https://zh.wikipedia.org/wiki/Hello_World程序样例

[[email protected] ~]#vim /data/hello.sh
#!/bin/bash
# ------------------------------------------
# Filename: hello.sh
# Version: ?1.0
# Date: 2017/06/01
# Author: wang
# Email:        @qq.com
# Website:           .com
# Description: This is the first script
# Copyright: 2017
# License: GPL
# ------------------------------------------

经典写法

echo "hello, world"

流行写法

echo ‘Hello, world!‘

执行方法1

[[email protected] ~]#bash /data/hello.sh

执行方法2

[[email protected] ~]#cat /data/hello.sh | bash

执行方法3

[[email protected] ~]#chmod +x /data/hello.sh

绝对路径

[[email protected] ~]#/data/hello.sh

相法路径

[[email protected] ~]#cd /data/;
[[email protected] ~]#./hello.sh

执行方法4,本方法可以实现执行远程主机的shell脚本

[[email protected] ~]#yum -y install httpd

[[email protected] ~]#systemctl start httpd

[[email protected] ~]#mv /data/hello.sh /var/www/html/

[[email protected] ~]#curl -s http://10.0.0.8/hello.sh|bash

范例:备份脚本

#!/bin/bash

#

#********************************************************************

#Author: wangxiaochun

#QQ: 29308620

#Date: 2019-12-20

#FileName: backup.sh

#URL: http://www.magedu.com

#Description: The test script

#Copyright (C): 2019 All rights reserved

#********************************************************************

echo -e "\033[1;32mStarting backup...\033[0m"

sleep 2

cp -av /etc/ /data/etcdate +%F/

echo -e "\033[1;32mBackup is finished\033[0m"

脚本调试

只检测脚本中的语法错误,但无法检查出命令错误,但不真正执行脚本
  bash -n /path/to/some_script
 调试并执行
  bash -x /path/to/some_script

范例

 [[email protected] script41]#cat -A f1.sh
 #!/bin/bash$
 #$
 #********************************************************************$
 #Author:^I^Iwangxiaochun$
 #QQ: ^I^I^I29308620$
 #Date: ^I^I^I2020-04-01$
 #FileNameM-oM-<M-^Z^I^If1.sh$
 #URL: ^I^I^Ihttp://www.magedu.com$
 #DescriptionM-oM-<M-^Z^I^IThe test script$
 #Copyright (C): ^I2020 All rights reserved$
 #********************************************************************$
 echo line1$
 hostnam$
 cat > test.txt <<EOF $
 aaa$
 bbb$
 ccc$
 EOF $
 $
 echo line22$
 [[email protected] script41]#bash -n f1.sh
 f1.sh: line 20: warning: here-document at line 14 delimited by end-of-file
 (wanted `EOF‘)

总结:脚本错误常见的有三种

语法错误,会导致后续的命令不继续执行,可以用bash -n 检查错误,提示的出错行数不一定是准确的

命令错误,后续的命令还会继续执行,用bash -n 无法检查出来 ,可以使用 bash -x 进行观察

逻辑错误:只能使用 bash -x 进行观察

二级标题

3.变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

变量类型

内置变量,如:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE

用户自定义变量

不同的变量存放的数据不同,决定了以下

1. 数据存储方式

2. 参与的运算

3. 表示的数据范围

变量数据类型:

字符

数值:整型、浮点型,bash 不支持浮点数

编程语言分类

静态和动态语言

 静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如:java,c

 动态编译语言:不用事先声明,可随时改变类型,如:bash,Python

强类型和弱类型语言

 强类型语言:不同类型数据操作,必须经过强制转换才同一类型才能运算,如java , c# ,
 python
 如:以下python代码
 print(‘magedu‘+ 10) 提示出错,不会自动转换类型
 print(‘magedu‘+str(10)) 结果为magedu10,需要显示转换类型

 弱类型语言:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;参与运算会
 自动进行隐式类型转换;变量无须事先定义可直接调用
 如:bash ,php,javascript

Shell中变量命名法则

不能使程序中的保留字:如:if, for

只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反

见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM

统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName

变量名大写:STUDENT_NAME

局部变量小写

函数名小写

变量定义和引用

 变量的生效范围等标准划分变量类型

 普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell
 进程均无效

 环境变量:生效范围为当前shell进程及其子进程

 本地变量:生效范围为当前shell进程中某代码片断,通常指函数

 变量赋值:
  name=‘value‘

  value 可以是以下多种形式
   直接字串:name=‘root‘
   变量引用:name="$USER"
   命令引用:name=`COMMAND` 或者 name=$(COMMAND)

   注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚
   本结束,也会自动删除

变量引用:

$name

${name}

  弱引用和强引用
   "$name " 弱引用,其中的变量引用会被替换为变量值
   ‘$name ‘ 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

 范例
  [[email protected] ~]#TITLE=‘cto‘
  [[email protected] ~]#echo $TITLE
  cto
  [[email protected] ~]#echo I am $TITLE
  I am cto
  [[email protected] ~]#echo "I am $TITLE"
  I am cto

  [[email protected] ~]#echo ‘I am $TITLE‘
  I am $TITLE
  [[email protected] ~]#NAME=$USER
  [[email protected] ~]#echo $NAME
  root
  [[email protected] ~]#USER=`whoami`
  [[email protected] ~]#echo $USER
  root

  [[email protected] ~]#FILE=`ls /run`
  [[email protected] ~]#echo $FILE
  agetty.reload atd.pid auditd.pid autofs.fifo-misc autofs.fifo-net console
  cron.reboot cryptsetup dbus faillock fsck initctl initramfs lock log mount
  NetworkManager plymouth rsyslogd.pid screen sepermit setrans sshd.pid sssd.pid
  sudo systemd tmpfiles.d tuned udev user utmp vmware

  [[email protected] ~]#FILE=/etc/*
  [[email protected] ~]#echo $FILE
  /etc/adjtime /etc/aliases /etc/alternatives /etc/anacrontab /etc/at.deny
  /etc/audit /etc/authselect /etc/autofs.conf /etc/autofs_ldap_auth.conf

  [[email protected] ~]#NAMES="wang
  > zhang
  > zhao
  > li"
  [[email protected] ~]#echo $NAMES
  wang zhang zhao li
  [[email protected] ~]#echo "$NAMES"
  wang
  zhang
  zhao
  li

 范例:变量的间接赋值和引用
  [[email protected] ~]#TITLE=cto
  [[email protected] ~]#NAME=wang
  [[email protected] ~]#TITLE=$NAME
  [[email protected] ~]#echo $NAME
  wang
  [[email protected] ~]#echo $TITLE
  wang
  [[email protected] ~]#NAME=mage
  [[email protected] ~]#echo $NAME
  mage
  [[email protected] ~]#echo $TITLE
  wang

 范例:利用变量实现动态命令
  [[email protected] ~]#CMD=hostname
  [[email protected] ~]#$CMD
  centos8.wangxiaochun.com

 范例:显示系统信息
  [[email protected] scripts]#cat systeminfo.sh
  #!/bin/bash
  #
  #********************************************************************
  #Author: wangxiaochun
  #QQ: 29308620
  #Date: 2019-12-23
  #FileName: systeminfo.sh
  #URL: http://www.magedu.com
  #Description: Show system information
  #Copyright (C): 2019 All rights reserved
  #********************************************************************
  RED="\E[1;31m"
  GREEN="\E[1;32m"
  END="\E[0m"
  echo -e ?"$GREEN----------------------Host systeminfo--------------------$END"
  echo -e ?"HOSTNAME: ??$RED`hostname`$END"
  echo -e ?"IPADDR: ???$RED` ifconfig eth0|grep -Eo ‘([0-9]{1,3}\.){3}[0-9]
  {1,3}‘ |head -n1`$END"
  echo -e ?"OSVERSION: ??$RED`cat /etc/redhat-release`$END"
  echo -e ?"KERNEL: ???$RED`uname -r`$END"
  echo -e ?"CPU: ????$RED`lscpu|grep ‘Model name‘|tr -s ‘ ‘|cut -d : -f2`$END"
  echo -e ?"MEMORY: ???$RED`free -h|grep Mem|tr -s ‘ ‘ : |cut -d : -f2`$END"
  echo -e ?"DISK: ????$RED`lsblk |grep ‘^sd‘ |tr -s ‘ ‘ |cut -d " " -f4`$END"
  echo -e ?"$GREEN---------------------------------------------------------$END"

  [[email protected] scripts]#cat systeminfo.sh
  #!/bin/bash
  #
  #********************************************************************
  #Author: wangxiaochun
  #QQ: 29308620
  #Date: 2019-12-23
  #FileName: systeminfo.sh
  #URL: http://www.magedu.com
  #Description: Show system information
  #Copyright (C): 2019 All rights reserved
  #********************************************************************
  RED="\E[1;31m"
  GREEN="echo -e \E[1;32m"
  END="\E[0m"
  $GREEN----------------------Host systeminfo--------------------$END
  echo -e ?"HOSTNAME: ??$RED`hostname`$END"
  echo -e ?"IPADDR: ???$RED` ifconfig eth0|grep -Eo ‘([0-9]{1,3}\.){3}[0-9]
  {1,3}‘ |head -n1`$END"
  echo -e ?"OSVERSION: ??$RED`cat /etc/redhat-release`$END"
  echo -e ?"KERNEL: ???$RED`uname -r`$END"
  echo -e ?"CPU: ????$RED`lscpu|grep ‘Model name‘|tr -s ‘ ‘|cut -d : -f2`$END"
  echo -e ?"MEMORY: ???$RED`free -h|grep Mem|tr -s ‘ ‘ : |cut -d : -f2`$END"
  echo -e ?"DISK: ????$RED`lsblk |grep ‘^sd‘ |tr -s ‘ ‘ |cut -d " " -f4`$END"
  $GREEN---------------------------------------------------------$END

环境变量

   可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量

   一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程

   一般只在系统配置文件中使用,在脚本中较少使用

  变量声明和赋值
   #声明并赋值
   export name=VALUE
   declare -x name=VALUE
   #或者分两步实现
   name=VALUE
   export name

  显示所有环境变量:
    env
    printenv
    export
    declare -x

   删除变量:
    unset name

   bash内建的环境变量
    PATH
    SHELL
    USER
    UID
    HOME
    PWD
    SHLVL #shell的嵌套层数,即深度
    LANG
    MAIL
    HOSTNAME
    HISTSIZE_ ?     #下划线 表示前一命令的最后一个参数

只读变量

只读变量:只能声明定义,但后续不能修改和删除,即常量

声明只读变量:

readonly name

declare ?-r name

查看只读变量

readonly [-p]

declare -r

范例

[[email protected] ~]#readonly PI=3.14159

[[email protected] ~]#echo $PI

3.14159

[[email protected] ~]#PI=3.14

-bash: PI: readonly variable

[[email protected] ~]#unset PI

-bash: unset: PI: cannot unset: readonly variable

[[email protected] ~]#echo $PI

3.14159

[[email protected] ~]#exit

logout

[[email protected] ~]#echo $PI

[[email protected] ~]#

位置变量

位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数

$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置

$0 命令本身,包括路径

$* 传递给脚本的所有参数,全部参数合为一个字符串

[email protected] 传递给脚本的所有参数,每个参数为独立字符串

$# 传递给脚本的参数的个数

注意:[email protected] $* 只在被双引号包起来的时候才会有差异

清空所有位置变量

set --

        范例:
         [[email protected] ~]#cat /data/scripts/arg.sh
         #!/bin/bash
         #
         #********************************************************************
         #Author: wangxiaochun
         #QQ: 29308620
         #Date: 2020-04-01
         #FileName: arg.sh
         #URL: http://www.magedu.com
         #Description: The test script
         #Copyright (C): 2020 All rights reserved
         #********************************************************************
         echo "1st arg is $1"
         echo "2st arg is $2"
         echo "3st arg is $3"
         echo "10st arg is ${10}"
         echo "11st arg is ${11}"
         echo "The number of arg is $#"
         echo "All args are $*"
         echo "All args are [email protected]"
         echo "The scriptname is `basename $0`"

          [[email protected] ~]#bash /data/scripts/arg.sh {a..z}
          1st arg is a
          2st arg is b
          3st arg is c
          10st arg is j
          11st arg is k
          The number of arg is 26
          All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
          All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
          The scriptname is arg.sh

        范例 删库跑路之命令rm的安全实现
         [[email protected] ~]#cat /data/scripts/rm.sh
         #!/bin/bash
         #
         #********************************************************************
         #Author: wangxiaochun
         #QQ: 29308620
         #Date: 2020-04-01
         #FileName: /data/scripts/rm.sh
         #URL: http://www.magedu.com
         #Description: The test script
         #Copyright (C): 2020 All rights reserved
         #********************************************************************
         WARNING_COLOR="echo -e \E[1;31m"
         END="\E[0m"
         DIR=/tmp/`date +%F_%H-%M-%S`
         mkdir $DIR
         mv ?$* ?$DIR
         ${WARNING_COLOR}Move $* to $DIR $END
         [[email protected] ~]#chmod a+x /data/scripts/rm.sh
         [[email protected] ~]#alias rm=‘/data/scripts/rm.sh‘
         [[email protected] ~]#touch {1..10}.txt
         [[email protected] ~]#rm *.txt
         Move 10.txt 1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt 9.txt to /tmp/2020-
         04-01_15-15-28

        范例:$*和[email protected]的区别
         [[email protected] scripts]#cat f1.sh
         #!/bin/bash
         echo "f1.sh:all args are [email protected]"
         echo "f1.sh:all args are $*"
         ./file.sh "$*"
         [[email protected] scripts]#cat f2.sh
         #!/bin/bash
         echo "f2.sh:all args are [email protected]"
         echo "f2.sh:all args are $*"
         ./file.sh "[email protected]"
         [[email protected] scripts]#cat file.sh
         #!/bin/bash
         echo "file.sh:1st arg is $1"
         [[email protected] scripts]#./f1.sh a b c
         f1.sh:all args are a b c
         f1.sh:all args are a b c
         file.sh:1st arg is a b c
         [[email protected] scripts]#./f2.sh a b c
         f2.sh:all args are a b c
         f2.sh:all args are a b c
         file.sh:1st arg is a

退出状态码变量

当我们浏览网页时,有时会看到下图所显示的数字,表示网页的错误信息,我们称为状态码,在shell脚

本中也有相似的技术表示程序执行的相应状态。

进程执行后,将使用变量 $? 保存状态码的相关数字,不同的值反应成功或失败,$?取值范例 0-255

 $?的值为0 #代表成功
 $?的值是1到255 ?#代表失败

范例:
 [[email protected] scripts]#curl http://www.wangxiaochun.com &> /dev/null
 [[email protected] scripts]#echo $?

注意:

 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字

 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

展开命令行

展开命令执行顺序

把命令行分成单个命令词

展开别名

展开大括号的声明{}

展开波浪符声明 ~

命令替换$() 和 ``

再次把命令行分成命令词

展开文件通配*、?、[abc]等等

准备I/0重导向 <、>

运行命令

反斜线(\)会使随后的字符按原意解释

脚本安全和 set

set 命令:可以用来定制 shell 环境

$- 变量

h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选

项关闭

i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,

在脚本中,i选项是关闭的

m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等

B:braceexpand,大括号扩展

H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的

一个历史命令,“!n”返回第 n 个历史命令

范例

[[email protected] ~]#echo $-

himBHs

[[email protected] ~]#set +h

[[email protected] ~]#echo $-

imBHs

[[email protected] ~]#hash

-bash: hash: hashing disabled

 [[email protected] ~]#echo {1..10}
 1 2 3 4 5 6 7 8 9 10
 [[email protected] ~]#echo $-
 imBHs
 [[email protected] ~]#set +B
 [[email protected] ~]#echo $-
 imHs
 [[email protected] ~]#echo {1..10}
 {1..10}

set 命令实现脚本安全

-u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset

-e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit

-o option 显示,打开或者关闭选项

显示选项:set -o

打开选项:set -o 选项

关闭选项:set +o 选项

-x 当执行命令时,打印命令及其参数,类似 bash -x

格式化输出 printf

常用格式替换符

说明:%s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字

符宽,- 表示左对齐

常用转义字符

范例

[[email protected] ~]#printf "%s\n" 1 2 3 4

1

2

3

4

[[email protected] ~]#printf "%f\n" 1 2 3 4

1.000000

2.000000

3.000000

4.000000

.2f 表示保留两位小数

[[email protected] ~]#printf "%.2f\n" 1 2 3 4

1.00

2.00

3.00

4.00

[[email protected] ~]#printf "(%s)" 1 2 3 4;echo

(1)(2)(3)(4)

[[email protected] ~]#printf " (%s) " 1 2 3 4;echo ""

(1) (2) (3) (4)

[[email protected] ~]#printf "(%s)\n" 1 2 3 4

(1)

(2)

(3)

(4)

[[email protected] ~]#printf "%s %s\n" 1 2 3 4

1 2

3 4

[[email protected] ~]#printf "%s %s %s\n" 1 2 3 4

1 2 3

4

%-10s 表示宽度10个字符,左对齐

[[email protected] ~]#printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70

女 18 50

姓名 ??性别 ??年龄 ?体重

小明 ??男 ????20 ? 70

小红 ??女 ????18 ? 50

[[email protected] ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" $VAR

welcome

to

Magedu

[[email protected] ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" "$VAR"

welcome to Magedu

二级标题

4.运算

算术运算

shell 支持算术运算,但只支持整数,不支持小数

bash中的算术运算

+

/

% 取模,即取余数,示例:9%4=1,5%3=2

** 乘方

乘法符号有些场景中需要转义

实现算术运算:

(1) let var=算术表达式

(2) ((var=算术表达式)) 和上面等价

(3) var=$[算术表达式]

(4) var=$((算术表达式))

(5) var=$(expr arg1 arg2 arg3 ...)

(6) declare –i var = 数值

(7) echo ‘算术表达式‘ | bc

内建的随机数生成器变量:

$RANDOM ?取值范围:0-32767

范例

生成 0 - 49 之间随机数

echo $[$RANDOM%50]

随机字体颜色

[[email protected] ~]#echo -e "\033[1;$[RANDOM%7+31]hello\033[0m"

magedu

增强型赋值

+= i+=10 相当于 i=i+10

-= i-=j ?相当于 i=i-j

*=

/=

%=

++ i++,++i ?相当于 i=i+1

-- i--,--i ?相当于 i=i-1

范例

[[email protected] ~]#let i=10*2

[[email protected] ~]#echo $i

20

[[email protected] ~]#((j=i+10))

[[email protected] ~]#echo $j

30

自加3后自赋值

let count+=3

[[email protected] ~]#i=10

[[email protected] ~]#let i+=20 #相当于let i=i+20

[[email protected] ~]#echo $i

30

[[email protected] ~]#j=20

[[email protected] ~]#let i*=j

[[email protected] ~]#echo $i

600

自增,自减

let var+=1
let var++
let var-=1
let var--
[[email protected] ~]#unset i j ; i=1; let j=i++; echo "i=$i,j=$j"
i=2,j=1
[[email protected] ~]#unset i j ; i=1; let j=++i; echo "i=$i,j=$j"
i=2,j=2

[[email protected] ~]#expr 2 * 3
expr: syntax error: unexpected argument ‘anaconda-ks.cfg’
[[email protected] ~]#ls
anaconda-ks.cfg
[[email protected] ~]#expr 2 \* 3
6

[[email protected] ~]#echo "scale=3;20/3"|bc
6.666

[[email protected] ~]#i=10
[[email protected] ~]#j=20
[[email protected] ~]#declare -i result=i*j
[[email protected] ~]#echo $result
200

今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?

[[email protected] scripts]#cat chook_rabbit.sh

#!/bin/bash

HEAD=$1

FOOT=$2

RABBIT=$(((FOOT-HEAD-HEAD)/2))

CHOOK=$[HEAD-RABBIT]

echo RABBIT:$RABBIT

echo CHOOK:$CHOOK

[[email protected] scripts]#./chook_rabbit.sh 30 80

RABBIT:10

CHOOK:20

[[email protected] scripts]#

算出所有人的年龄总和

[[email protected] ~]#cat /data/nianling.txt

xiaoming=20

xiaohong=18

xiaoqiang=22

[[email protected] ~]#cut -d"=" -f2 /data/nianling.txt|tr ‘\n‘ + | grep -Eo ".[0-

9]"|bc

60

[[email protected] ~]#grep -Eo "[0-9]+" /data/nianling.txt | tr ‘\n‘ + | grep -Eo ".

[0-9]"|bc

60

逻辑运算

true, false

1, 0

与:&:和0相与,结果为0,和1相与,结果保留原值

1 与 1 = 1

1 与 0 = 0

0 与 1 = 0

0 与 0 = 0

或:|:和1相或结果为1,和0相或,结果保留原值

1 或 1 = 1

? 1 或 0 = 1

0 或 1 = 1

0 或 0 = 0

非:!

! 1 = 0 ! true

! 0 = 1 ! false

异或:^

异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出

另一个值Y

1 ^ 1 = 0

1 ^ 0 = 1

0 ^ 1 = 1

0 ^ 0 = 0

范例

[[email protected] ~]#true

[[email protected] ~]#echo $?

0

[[email protected] ~]#false

[[email protected] ~]#echo $?

1

[[email protected] ~]#! true

[[email protected] ~]#echo $?

1

[[email protected] ~]#! false

[[email protected] ~]#echo $?

0

[[email protected] ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y

x=20,y=10

[[email protected] ~]#x=10;y=20;x=$[xy];y=$[xy];x=$[x^y];echo x=$x,y=$y

x=20,y=10

短路运算

短路与

CMD1 短路与 CMD2

第一个CMD1结果为真 (1),第二个CMD2必须要参与运算,才能得到最终的结果

第一个CMD1结果为假 (0),总的结果必定为0,因此不需要执行CMD2

短路或

CMD1 短路或 CMD2

第一个CMD1结果为真 (1),总的结果必定为1,因此不需要执行CMD2

第一个CMD1结果为假 (0),第二个CMD2 必须要参与运算,,才能得到最终的结果

二级标题

5.条件测试

条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成测试过程,实现评估布尔声明,以便用在条件性环境下进行执行

若真,则状态码变量 $? 返回0

若假,则状态码变量 $? 返回1

条件测试命令

条件测试命令

test EXPRESSION

[ EXPRESSION ] #和test 等价,建议使用 [ ]

[[ EXPRESSION ]]

注意:EXPRESSION前后必须有空白字符

变量测试
 -v VAR 变量VAR是否设置
 -R VAR 变量VAR是否设置并引用

范例
  [[email protected] ~]#unset x
  [[email protected] ~]#test -v x
  [[email protected] ~]#echo $?
  1
  [[email protected] ~]#x=10
  [[email protected] ~]#test -v x
  [[email protected] ~]#echo $?
  0
  [[email protected] ~]#y=
  [[email protected] ~]#test -v y
  [[email protected] ~]#echo $?
  0

 #注意 [ ] 需要空格,否则会报下面错误
  [[email protected] ~]#[-v y]
  -bash: [-v: command not found
  [[email protected] ~]#[ -v y ]
  [[email protected] ~]#echo $?
  0

数值测试

-eq 是否等于

-ne 是否不等于

-gt 是否大于

-ge 是否大于等于

-lt 是否小于

-le 是否小于等于

范例

[[email protected] ~]#i=10

[[email protected] ~]#j=8

[[email protected] ~]#[ $i -lt $j ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[ $i -gt $j ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ i -gt j ]

-bash: [: i: integer expression expected

字符串测试

test和 [ ]用法

-z STRING 字符串是否为空,没定义或空为真,不空为假,

-n STRING 字符串是否不空,不空为真,空为假

? STRING ?同上

STRING1 = STRING2 是否等于,注意 = 前后有空格

STRING1 != STRING2 是否不等于

ascii码是否大于ascii码

< 是否小于

[[]] 用法,建议,当使用正则表达式或通配符使用,一般情况使用 [ ]

== 左侧字符串是否和右侧的PATTERN相同

注意:此表达式用于[[ ]]中,PATTERN为通配符

=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配

注意: 此表达式用于[[ ]]中;扩展的正则表达式

范例

[[email protected] ~]#unset str

[[email protected] ~]#[ -z "$str" ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#str=""

[[email protected] ~]#[ -z "$str" ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#str=" "

[[email protected] ~]#[ -z "$str" ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[ -n "$str" ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#unset str

[[email protected] ~]#[ -n "$str" ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[ "$str" ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#str=magedu

[[email protected] ~]#[ "$str" ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#str=magedu

[[email protected] ~]#[ "$str" ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#str1=magedu

[[email protected] ~]#str2=mage

[[email protected] ~]#[ $str1 = $str2 ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#str2=magedu

[[email protected] ~]#[ $str1 = $str2 ]

[[email protected] ~]#echo $?

0

在比较字符串时,建议变量放在“ ”中

[[email protected] ~]#[ "$NAME" ]

[[email protected] ~]#NAME="I love linux"

[[email protected] ~]#[ $NAME ]

-bash: [: love: binary operator expected

[[email protected] ~]#[ "$NAME" ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ I love linux ]

-bash: [: love: binary operator expected

通配符

[[email protected] ~]#FILE=test.log

[[email protected] ~]#[[ "$FILE" == *.log ]]

[[email protected] ~]#echo $?

0

[[email protected] ~]#FILE=test.txt

[[email protected] ~]#[[ "$FILE" == *.log ]]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[[ "$FILE" != *.log ]]

[[email protected] ~]#echo $?

0

正则表达式

[[email protected] ~]#[[ "$FILE" =~ .log$ ]]

[[email protected] ~]#echo $?

1

[[email protected] ~]#FILE=test.log

[[email protected] ~]#[[ "$FILE" =~ .log$ ]]

[[email protected] ~]#echo $?

0

[[email protected] ~]#N=100

[[email protected] ~]#[[ "$N" =~ [1]+$ ]]

[[email protected] ~]#echo $?

0

[[email protected] ~]#N=Magedu10

[[email protected] ~]#[[ "$N" =~ [2]+$ ]]

[[email protected] ~]#echo $?

1

[[email protected] ~]#IP=1.2.3.4

[[email protected] ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]

[[email protected] ~]#echo $?

0

[[email protected] ~]#IP=1.2.3.4567

[[email protected] ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}

([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]

[[email protected] ~]#echo $?

1

通配符

[[email protected] ~]#NAME="linux1"

[[email protected] ~]#[[ "$NAME" == linux* ]]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[[ "$NAME" == "linux" ]]

[[email protected] ~]#echo $?

1

[[email protected] ~]#NAME="linux"

[[email protected] ~]#[[ "$NAME" == "linux*" ]]

[[email protected] ~]#echo $?

0

结论:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*, 需要加“” 或转义

文件测试

-a FILE:同 -e

-e FILE: 文件存在性测试,存在为真,否则为假

-b FILE:是否存在且为块设备文件

-c FILE:是否存在且为字符设备文件

-d FILE:是否存在且为目录文件

-f FILE:是否存在且为普通文件

-h FILE 或 -L FILE:存在且为符号链接文件

-p FILE:是否存在且为命名管道文件

-S FILE:是否存在且为套接字文件

范例

[[email protected] ~]#[ -a /etc/nologin ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#! [ -a /etc/nologin ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ -d /etc ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ -d /etc/issue ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[ -L /bin ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ -L /bin/ ]

[[email protected] ~]#echo $?

1

文件权限测试

-r FILE:是否存在且可读

-w FILE: 是否存在且可写

-x FILE: 是否存在且可执行

-u FILE:是否存在且拥有suid权限

-g FILE:是否存在且拥有sgid权限

-k FILE:是否存在且拥有sticky权限

注意:最终结果由用户对文件的实际权限决定,而非文件属性决定

范例

[[email protected] ~]#[ -w /etc/shadow ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ -x /etc/shadow ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[ -w test.txt ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#chattr +i test.txt

[[email protected] ~]#lsattr test.txt

----i-------------- nianling.txt

[[email protected] ~]#[ -w test.txt ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#chattr -i test.txt

[[email protected] ~]#[ -w test.txt ]

[[email protected] ~]#echo $?

0

文件属性测试

-s FILE #是否存在且非空

-t fd #fd 文件描述符是否在某终端已经打开

-N FILE #文件自从上一次被读取之后是否被修改过

-O FILE #当前有效用户是否为文件属主

-G FILE #当前有效用户是否为文件属组

FILE1 -ef FILE2 #FILE1是否是FILE2的硬链接

FILE1 -nt FILE2 #FILE1是否新于FILE2(mtime)

FILE1 -ot FILE2 #FILE1是否旧于FILE2

关于 () 和 {}

CMD1;CMD2;...)和 { CMD1;CMD2;...; } 都可以将多个命令组合在一起,批量执行

( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash

搜索(list)

{ list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list; }

范例: () 和 {}

[[email protected] ~]#name=mage;(echo $name;name=wang;echo $name );echo $name

mage

wang

mage

[[email protected] ~]#name=mage;{ echo $name;name=wang;echo $name; } ;echo $name

mage

wang

wang

[[email protected] ~]#umask

0022

[[email protected] ~]#(umask 066;touch f1.txt)

[[email protected] ~]#ll f1.txt

-rw------- 1 root root 0 Dec 23 16:58 f1.txt

[[email protected] ~]#umask

0022

[[email protected] ~]#( cd /data;ls )

test.log

[[email protected] ~]#pwd

/root

[[email protected] ~]#{ cd /data;ls; }

test.log

[[email protected] data]#pwd

/data

[[email protected] data]#

()会开启子shell

[[email protected] ~]#echo $BASHPID

1920

[[email protected] ~]#( echo $BASHPID;sleep 100)

1979

[[email protected] ~]#pstree -p

├─sshd(719)───sshd(1906)───sshd(1919)─┬─bash(1920)───bash(1979)───sleep(1980)

{ } 不会开启子shell

[[email protected] ~]#echo $BASHPID

1920

[[email protected] ~]#{ echo $BASHPID; }

1920

组合测试条件

第一种方式 [ ]

[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真

[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为

[ ! EXPRESSION ] 取反

说明: -a 和 -o 需要使用测试命令进行,[[ ]] 不支持

范例

[[email protected] ~]#ll /data/scrips/test.sh

-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh

[[email protected] ~]#[ -f $FILE -a -x $FILE ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#chmod +x /data/scripts/test.sh

[[email protected] ~]#ll /data/scripts/test.sh

-rwxr-xr-x 1 root root 382 Dec 23 09:32 /data/script40/test.sh

[[email protected] ~]#[ -f $FILE -a -x $FILE ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#chmod -x /data/scripts/test.sh

[[email protected] ~]#ll /data/scripts/test.sh

-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh

[[email protected] ~]#[ -f $FILE -o -x $FILE ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#[ -x $FILE ]

[[email protected] ~]#echo $?

1

[[email protected] ~]#[ ! -x $FILE ]

[[email protected] ~]#echo $?

0

[[email protected] ~]#! [ -x $FILE ]

0

第二种方式 [[ ]]

COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN

如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2

COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE

如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2

! COMMAND ?#非,取反

范例

[[email protected] ~]#test "A" = "B" && echo "Strings are equal"

[[email protected] ~]#test "A"-eq "B" && echo "Integers are equal"

[[email protected] ~]#[ "A" = "B" ] && echo "Strings are equal"

[[email protected] ~]#[ "$A" -eq "$B" ] && echo "Integers are equal"

[[email protected] ~]#[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

[[email protected] ~]#[ -z "$HOSTNAME" -o "$HOSTNAME" = "localhost.localdomain" ]&&

hostname www.magedu.com

[[email protected] ~]#id wang &> /dev/null || ?useradd wang

[[email protected] ~]#id zhang &> /dev/null || ?useradd zhang

[[email protected] ~]#getent passwd zhang

zhang?1002:1002::/home/zhang:/bin/bash

[[email protected] ~]#grep -q no_such_user /etc/passwd || echo ‘No such user‘

No such user

[[email protected] ~]#[ -f “$FILE” ] && [[ “$FILE”=~ .*\.sh$ ]] && chmod +x $FILE
[[email protected] ~]#ping -c1 -W1 172.16.0.1 &> /dev/null && echo ‘172.16.0.1 is
up‘ || (echo ‘172.16.0.1 is unreachable‘; exit 1)
172.16.0.1 is up
[[email protected] ~]#IP=10.0.0.111;ping -c1 -W1 $IP &> /dev/null && echo $IP is up
|| echo $IP is down
10.0.0.111 is down
[[email protected] ~]#IP=10.0.0.1;ping -c1 -W1 $IP &> /dev/null && echo $IP is up ||
echo $IP is down
10.0.0.1 is up

范例:&& 和 || 组合使用

[[email protected] ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist"

wang is exist

[[email protected] ~]#NAME=wange; id $NAME &> /dev/null || echo "$NAME is not

exist"

wange is not exist

[[email protected] ~]#NAME=wange; id $NAME &> /dev/null && echo "$NAME is exist" ||

echo "$NAME is not exist"

wange is not exist

[[email protected] ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist" ||

echo "$NAME is not exist"

wang is exist

[[email protected] ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist" ||

echo "$NAME is not exist"

wang is exist

[[email protected] ~]#NAME=wang; id $NAME &> /dev/null || echo "$NAME is not exist"

&& echo "$NAME is exist"

wang is exist

[[email protected] ~]#NAME=wange; id $NAME &> /dev/null || echo "$NAME is not

exist" && echo "$NAME is exist"

wange is not exist

wange is exist

结论:如果&& 和 || 混合使用,&& 要在前,|| 放在后

[[email protected] ~]#NAME=wange; id $NAME &> /dev/null && echo "$NAME is exist" ||
useradd $NAME
[[email protected] ~]#id wange
uid=1002(wange) gid=1002(wange) groups=1002(wange)
[[email protected] ~]#NAME=wangge; id $NAME &> /dev/null && echo "$NAME is exist" ||
( useradd $NAME; echo $NAME is created )
wangge is created
[[email protected] ~]#id wangge
uid=1003(wangge) gid=1003(wangge) groups=1003(wangge)
[[email protected] ~]#NAME=wanggege; id $NAME &> /dev/null && echo "$NAME is exist"
|| { useradd $NAME; echo $NAME is created; }
wanggege is created

范例:网络状态判断

[[email protected] ~]#cat /data/scripts/ping.sh

#!/bin/bash

IP=172.16.0.1

ping -c1 -W1 $IP &> /dev/null && echo "$IP is up" || { ?echo "$IP is

unreachable"; exit; }

echo "Script is finished"

[[email protected] ~]#bash /data/scripts/ping.sh

172.16.0.1 is up

Script is finished

磁盘空间的判断

[[email protected] ~]#cat /data/script40/disk_check.sh

#!/bin/bash

WARNING=80

SPACE_USED=df|grep ‘^/dev/sd‘|tr -s ‘ ‘ %|cut -d% -f5|sort -nr|head -1

[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $SPACE_USED,will be full"

| mail -s diskwaring root

磁盘空间和Inode号的检查脚本
 [[email protected] scripts]#cat disk_check.sh
 #!/bin/bash
 WARNING=80
 SPACE_USED=`df | grep ‘^/dev/sd‘|grep -oE ‘[0-9]+%‘|tr -d %| sort -nr|head -1`
 INODE_USED=`df -i | grep ‘^/dev/sd‘|grep -oE ‘[0-9]+%‘|tr -d %| sort -nr|head
 -1`
 [ "$SPACE_USED" -gt $WARNING -o "$INODE_USED" -gt $WARNING ] && echo "DISK
 USED:$SPACE_USED%, INODE_USED:$INODE_USED,will be full" | mail -s "DISK Warning"
 [email protected]

使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变

量,所有剩余单词都被分配给最后一个变量

常见选项:
 -p ?指定要显示的提示
 -s ?静默输入,一般用于密码
 -n N 指定输入的字符长度N
 -d ‘字符‘ ?输入结束符
 -t N TIMEOUT为N秒

范例
  [[email protected] ~]#read
  wangxiaochun
  [[email protected] ~]#echo $REPLY
  wangxiaochun
  [[email protected] ~]#read NAME TITLE
  wang cto
  [[email protected] ~]#echo $NAME
  wang
  [[email protected] ~]#echo $TITLE
  cto
  [[email protected] ~]#echo magedu | read NAME
  [[email protected] ~]#echo $NAME
  [[email protected] ~]#echo magedu | { read NAME; echo $NAME; }
  magedu
  [[email protected] ~]#read -p "Please input your name: " NAME
  Please input your name: wang
  [[email protected] ~]#echo $NAME
  wang

面试题 read和输入重定向
 [[email protected] scripts]#cat test.txt
 1 2
 [[email protected] scripts]#read i j < test.txt ; echo i=$i j=$j
 i=1 j=2
 [[email protected] scripts]#echo 1 2 | read x y ; echo x=$x y=$y
 x= y=
 [[email protected] ~]#echo 1 2 | ( read x y ; echo x=$x y=$y )
 x=1 y=2
 [[email protected] ~]#echo 1 2 | { read x y ; echo x=$x y=$y; }
 x=1 y=2
 [[email protected] ~]#man bash

 [[email protected] scripts]#cat read.sh
 #!/bin/bash
 read -p "Are you rich?yes or no: " ANSWER
 [[ $ANSWER =~ ^[Yy]|[Yy][Ee][Ss]$ ]] && echo "You are rich" || echo "Good Good
 Study,Day Day Up!"

鸡兔同笼算法,今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
 [[email protected] ~]#cat /data/script40/chook_rabbit.sh
 #!/bin/bash
 read -p "请输入头的数量: " HEAD
 read -p "请输入脚的数量: " FOOT
 RABBIT=$[FOOT/2-HEAD]
 CHOOK=$[HEAD-RABBIT]
 echo "兔子: " $RABBIT
 echo "鸡: " $CHOOK

实现运维工作菜单
 [[email protected] scripts]#cat work_menu.sh
 #!/bin/bash
 echo -en "\E[$[RANDOM%7+31];1m"
 cat <<EOF
 请选择:
 1)备份数据库
 2)清理日志
 3)软件升级
 4)软件回滚
 5)删库跑路
 EOF
 echo -en ‘\E[0m‘
 read -p ?"请输入上面数字1-5: " MENU
 [ $MENU -eq 1 ] && ./backup.sh
 [ $MENU -eq 2 ] && echo "清理日志"
 [ $MENU -eq 3 ] && echo "软件升级"
 [ $MENU -eq 4 ] && echo "软件回滚"
 [ $MENU -eq 5 ] && echo "删库跑路"

二级标题

6.配置用户环境

按生全局配置效范围划分两类

全局配置:

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc

个人配置:

~/.bash_profile

~/.bashrc

shell登录两种方式分类

交互式登录

直接通过终端输入账号密码登录

使用 su - UserName 切换的用户

配置文件执行顺序:

/etc/profile.d/*.sh

/etc/bashrc

/etc/profile

/etc/bashrc ?#此文件执行两次

.bashrc

.bash_profile

注意:文件之间的调用关系,写在同一个文件的不同位置,将影响文件的执行顺序

非交互式登录

u UserName

图形界面下打开的终端

执行脚本

任何其它的bash实例

/etc/profile.d/*.sh

/etc/bashrc

.bashrc

按功能划分分类

profile类

profile类为交互式登录的shell提供配置全局:/etc/profile, /etc/profile.d/*.sh

个人:~/.bash_profile

功用:

(1) 用于定义环境变量

(2) 运行命令或脚本

Bashrc类
 bashrc类:为非交互式和交互式登录的shell提供配置
 全局:/etc/bashrc
 个人:~/.bashrc
 功用:
 (1) 定义命令别名和函数
 (2) 定义本地变量

编辑配置文件生效

修改profile和bashrc文件后需生效两种方法:

1. 重新启动shell进程

2. source|. 配置文件

Bash 退出任务

保存在~/.bash_logout文件中(用户),在退出登录shell时运行

功能:

创建自动备份

清除临时文件

二级标题

7.条件选择

if 语句

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else

COMMANDS; ] fi

单分支

if 判断条件;then

? 条件为真的分支代码

fi

双分支

if 判断条件; then

条件为真的分支代码

else

条件为假的分支代码

fi

多分支

if 判断条件1; then

条件1为真的分支代码

elif 判断条件2; then

条件2为真的分支代码

elif 判断条件3; then

条件3为真的分支代码

...

else

以上条件都为假的分支代码

fi

说明:

多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句

if 语句可嵌套

范例

根据命令的退出状态来执行命令

if ping -c1 -W2 station1 &> /dev/null; then ?

echo ‘station1 is UP‘

elif ?grep -q ‘station1‘ ~/maintenance.txt; ?then ?

echo ‘station1 is undergoing maintenance‘

else

echo ‘station1 is unexpectedly DOWN!‘ ?

exit 1

fi

身体质量指数 (BMI

[[email protected] ~]#cat if_bmi.sh

#!/bin/bash

read -p "请输入身高(m为单位): " HIGH

if [[ ! "$HIGH" =~ [3].?[0-9]{,2}$ ]];then

echo "输入错误的身高"

exit 1

fi

read -p "请输入体重(kg为单位): " WEIGHT

if [[ ! "$WEIGHT" =~ [4]{1,3}$ ]];then echo "输入错误的体重"; exit 1; fi

BMI=echo $WEIGHT/$HIGH^2|bc

if [ $BMI ?-le 18 ] ;then

echo "太瘦了,多吃点"

elif [ $BMI ?-lt 24 ] ;then

echo "身材很棒!"

else

echo "太胖了,注意节食,加强运动"

fi

条件判断 case 语句

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

case 变量引用 in

PAT1)

分支1

;;

PAT2)

分支2

;;

...

*)

默认分支

;;

esac

case支持glob风格的通配符:

*: 任意长度任意字符

?: 任意单个字符

[]:指定范围内的任意单个字符

|: ?或,如 a或b

范例

[[email protected] scripts]#cat case_yesorno.sh

!/bin/bash

read -p "Do you agree(yes/no)? " INPUT

INPUT=echo $INPUT | tr ‘A-Z‘ ‘a-z‘

case $INPUT in

y|yes)

??? echo "You input is YES"

?? ;;

n|no)

??? echo "You input is NO"

?? ;;

*)

??? echo "Input fales,please input yes or no!"

esac

[[email protected] scripts]#cat case_yesorno2.sh

!/bin/bash

read -p "Do you agree(yes/no)? " INPUT

case $INPUT in

[yY]|[Yy][Ee][Ss])

?? echo "You input is YES"

? ;;

[Nn]|[Nn][Oo])

?? echo "You input is NO"

? ;;

*)

?? echo "Input fales,please input yes or no!" ????????????????

??????????????

esac

运维菜单实现版本2

[[email protected] scripts]#cat work_menu.sh

!/bin/bash

echo -en "\E[$[RANDOM%7+31];1m"

cat <<EOF

请选择:

1)备份数据库

2)清理日志

3)软件升级

4)软件回滚

5)删库跑路

EOF

echo -en ‘\E[0m‘

read -p ?"请输入上面数字1-5: " MENU

case $MENU in

1)

? ./backup.sh

? ;;

2)

?? echo "清理日志"

;;

3)

?? echo "软件升级"

? ;;

4)

?? echo "软件回滚"

? ;;

5)

?? echo "删库跑路"

? ;;

*)

?? echo "INPUT FALSE!"

esac


  1. 0-9 ??
  2. 0-9 ??
  3. 0-2 ??
  4. 0-9 ??

原文地址:https://www.cnblogs.com/zhaihongyu/p/12640439.html

时间: 2024-10-25 19:23:51

shell 脚本编程基础篇的相关文章

Linux中的shell脚本编程——基础篇

概述: shell脚本在Linux系统管理员的运维工作中非常重要.shell脚本能够帮助我们很方便的管理服务器,因为我们可以指定一个任务计划,定时的去执行某一个脚本以满足我们的需求.本篇将从编程基础.脚本基本格式.变量.运算.条件测试这几个方面详细介绍shell脚本编程的基础内容,也是我们必须要掌握熟练的内容. 一.编程环境 1.程序:指令+数据 程序编程的风格有两种: 过程式:以指令为中心,数据服务与指令 对象式:以数据为中心,指令服务于数据 2.程序的执行方式: □计算机:只能识别二进制文件

Shell脚本编程——基础篇

Shell脚本概念 1.将要执行的命令按顺序保存到一个文本文件2.给该文件可执行权限,便可运行3.可结合各种shell控制语句以完成更复杂的操作 Shell脚本应用场景 1.重复性操作2.批量事务处理3.自动化运维4.服务运行状态监控5.定时任务执行 完善的shell脚本构成 1.脚本声明2.可执行语句3.注释文字 Shell的作用--命令解释器,"翻译官" 执行脚本文件方法大全 方法一:脚本文件路径(绝对路径和相对路径)方法二:sh脚本文件路径方法三:source脚本文件路径拓展方法

Linux shell脚本编程基础之练习篇

shell脚本编程基础之练习篇. 1.编写一个脚本使我们在写一个脚本时自动生成”#!/bin/bash”这一行和注释信息. #!/bin/bash if [ $# -ne 1 ] then echo "请输入一个参数" exit else echo "参数正确" newfile=$1 fi #echo `grep "^#\!" ${newfile}` if ! grep "^#\!" ${newfile} &>/

shell脚本编程高级篇

SHELL脚本编程进阶循环执行:简单来说就是把一些指令重复循环. 循环代码具体的指令有三种: for , while , until其中for, while用的最多.for循环 for 变量名 in 列表;do 循环体 done 关键字的帮助都是用help来查询.for循环语法:在shell编程中 for,in,do,done.这些都是他的关键字,其中循环的指零就放在do和done之间.WORDS决定了循环次数.循环的次数由in 后面跟的WORDS(字符串)的数量决定.字符串的个数决定了do和d

8.15_Linux之bash shell脚本编程入门篇(二)以及文件查找和压缩的使用

bash shell脚本编程入门篇(二) read命令的使用 作用: 使用read来把输入值分配给一个或多个shell变量: -p指定要显示的提示 -t TIMEOUT read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量 EX.read -p "Enter a filename:" FILE 条件选择之if的使用 if的作用:选择执行(注意:if语句可嵌套) 单分支 if 判断条件;then 条件为真的分支代码 fi EX.单分支案例 双分支 if

8.17_Linux之bash shell脚本编程入门篇(三)之循环以及函数function的使用

bash shell脚本编程入门篇(三)之循环 什么是循环执行? 将某代码段重复运行多次 重复运行多少次: 循环次数事先已知 循环次数事先未知 有进入条件和退出条件 相关命令:for, while, until,selet, for命令的使用 作用: 依次将列表中的元素赋值给"变量名"; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束 命令格式: for 变量名 in 列表; do 循环体(正常执行的执行命令) 语句1 语句2 语句3 ... done 列表生成方式: (

第九章、shell脚本编程基础

第九章.shell脚本编程基础 本章内容 编程基础 脚本基本格式 变量 运算 条件测试 配置用户环境 编程基础 程序:指令+数据 程序编程风格: 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心,指令服务于数据 shell程序:提供了编程能力,解释执行 程序的执行方式 计算机:运行二进制指令 编程语言: 低级:汇编 高级: 编译:高级语言-->编译器-->目标代码 java,C# 解释:高级语言-->解释器-->机器代码 shell, perl, python (系统后台

文本处理工具和正则表达式、shell脚本编程基础-第四周

第四周-文本处理工具和正则表达式.shell脚本编程基础1. 统计出/etc/passwd文件中其默认shell为非/sbin/nologin的用户的个数,并将用户都显示出来grep -v '/sbin/nologin' /etc/passwd|wc -lgrep -v '/sbin/nologin' /etc/passwd|cut -d: -f12. 查出用户UID最大值的用户名,UID及shell类型.cut -d: -f1,3,7 /etc/passwd|sort -t: -k2 -nr

Shell脚本编程基础

什么是Shell 操作系统最外层的程序,shell通过提示符让用户输入,向操作系统解释该输入,然后处理来自操作系统的任何结果输出来,管理用户与操作系统之间的交互. Shell是一个用户跟操作系统之间的一个命令解释器.Shell是用户与Linux操作系统之间沟通的桥梁.用户可以输入命令执行,又可以利用 Shell脚本编程去运行. 为什么要用到shell shell是一个交互式程序,当用户输入一条命令,shell就解释一条,一次只处理一条命令.如果我们一些复杂操作,逐个敲命令工作量就会增大,因此,我