SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)

文章目录

  • 一、第一天(Shell脚本编程基础)
    • 作者视频ppt部分
    • 作者视频操作
      • 编写一个hello.sh可执行文件
      • 使hello.sh可以到处运行
      • 没有执行权限的执行方式
      • 下载httpd(web服务器)
      • curl字符界面浏览器
    • 命令列表
      • 凌乱笔记
    • 作业
    • 重点:
  • 第二天(shel脚本编程基础之变量用法详解)
    • 总结:脚本错误常见的有三种
    • 课堂操作
      • 变量的赋值方式
      • 探索变量赋值
  • 第三天(shell脚本编程基础之变量用法详解)
    • 部分ppt
    • 课堂操作
      • 操作变量
      • 环境变量的继承
      • 系统环境变量
      • 显示系统信息,编写systeminfo.sh 文件
  • 第四天(脚本编程变量详解)
    • 部分ppt
    • 课堂操作
      • 老师优化过的系统信息脚本
      • 使ip地址固定(固定网卡)
      • 使用位置变量
      • 安全删除(实则移动)
      • \$*和\$@的区别
  • 第五天(脚本编程特殊变量和脚本安全avi)
    • 部分ppt
    • 课堂操作
      • 脚本错误立即退出
      • 错误的危险脚本
  • 第六天(shell脚本编程中的算术和逻辑运算)
    • 部分ppt
    • 课堂操作
      • 计算的例子
      • 随机字体颜色
      • 鸡兔同笼问题
      • 异或运算,使x,y的值对换
  • 第七天(shell脚本编程之测试语句test实现变量数字和字符串判断详解)
    • 部分ppt
    • 课堂操作
      • 年龄相加
      • 查看是否存在n变量
      • 判定字符串
  • 第八天(shel脚本编程之条件测试语句实现逻辑判断详解)
    • 部分ppt
    • 课堂操作
      • [[]]中使用扩展的正则表达式
      • 字符串的判定
      • 判定是否为文件夹
  • 第九天(shel脚本编程条件判断和接入输入处理)
    • 课堂操作
      • 判定用户是否存在
      • 硬盘容量和节点告警
      • linux 设置邮箱
      • read操作,和用户交互
      • 是否有钱脚本
  • 第十天(shell环境配置文件)
    • 课堂操作
      • 管道命令会开启一个子进程
      • vim管理器方式复制错位,自动对齐
  • 第十一天(shell编程的条件判断if和case讲解)
    • 课堂操作
      • 判定胖瘦
      • 修改tab键变4个空格
      • yesORno脚本
  • 第十二天(shell脚本编程进阶之for循环)
    • 部分ppt
    • 课堂操作
      • 循环输出1~10
      • 循环1加到100
      • 打印.log类型的路径
      • sum.sh,相加文件编写
      • 99乘法表,for
  • 第十三天(shell脚本编程进阶之for循环语法2)
    • 部分ppt
    • 课堂操作
      • 文件改名,后缀都改为bak,for_rename.sh
      • 面试题:创建YYYY-MM-DD,当前日期一年前365天到目前共365个目录,里面有10个文件
      • 测试网络的网络是否连通
      • 打印背景颜色
  • 第十四天(shell脚本编程进阶之while循环和continue和break)
    • 部分ppt
    • 课堂操作
      • 系统初始化设置脚本
  • 第十五天(shell脚本编程进阶之shift与select相关技术)
    • 部分ppt
    • 课堂操作
      • shift.sh示例
      • select示例
  • 第十六天(shell编程脚本进阶之函数)
    • 课堂操作
      • 关闭防火墙脚本
  • 第十七天(shell脚本编程进阶之函数高级用法递归)
    • 课堂操作
      • local变量
      • 环境函数
      • 函数递归-阶乘
      • fork炸弹
  • 第十八天(shell脚本编程进阶之高级工具expect等)
    • 部分ppt
    • 课堂操作
      • 安全退出处理
      • 一旦接受到回车,发送消息
      • 使用脚本登录ssh
      • 替我传输文件
      • 替我人工登录ssh
      • expect位置参数
      • shell脚本调用expect
  • 第十九天(shell脚本编程进阶之数组)
    • 部分ppt
    • 课堂操作
      • 生成数组
  • 第二十天(shell脚本编程进阶之变量和字符串高级用法)
    • 课堂操作
      • 处理数组
      • 生成10个随机数保存于数组中,并找出其最大值和最小值
      • 字符串切片
      • eval变量的间接调用
  • 参考文档

一、第一天(Shell脚本编程基础)

作者视频ppt部分

  • 1、编程基础
    Linus: Talk is cheap, show me the code

  • 1.1 程序组成
    程序: 算法+数据结构
    数据:是程序的核心
    算法:处理数据的方式
    数据结构: 数据在计算机中的类型和组织方式

  • 1.2 程序编程风格

  • 面向过程语言

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

    • 一种认识世界、分析世界的方法论。将万事万物抽象为各种对象
    • 类是抽象的概念,是万事万物的抽象,是一类事物的共同特征的集合
    • 对象是类的具象,是一个实体
    • 问题规模大,复杂系统
    • 以数据为中心,指令服务于数据
    • java,C#,python,golang等
  • 1.3 编程语言
    计算机: 运行二进制指令
    编程语言:人与计算机之间交互的语言。分为两种:低级语言和高级语言

  • 低级编程语言:
    机器:二进制的0和1的序列,称为机器指令。与自然语言差异太大,难懂、难写
    汇编:用一些助记符号替代机器指令,称为汇编语言
    如:ADDA,B将寄存器A的数与寄存器B的数相加得到的数放到寄存器A中汇编语言写好的程序需要汇编程序转换成机器指令
    汇编语言稍微好理解,即机器指令对应的助记符,助记符更接近自然语言

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

  • 编译和解释型语言
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第1张图片

  • 1.4 编程逻辑处理方式

  • 顺序结构流程

SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第2张图片

  • 分支结构流程1
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第3张图片

  • 分支结构流程2
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第4张图片

  • 循环结构流程1
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第5张图片

  • 循环结构流程2
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第6张图片

  • 三种处理逻辑

    • 顺序执行
    • 选择执行
    • 循环执行
  • 2、shell 脚本语言的基本结构

  • 2.1 shell脚本的用途

    • 自动化常用命令
    • 执行系统管理和故障排除
    • 创建简单的应用程序
    • 处理文本或文件
  • 2.2 shell脚本基本结构
    shell脚本编程:是基于过程式、解释执行的语言

  • 编程语言的基本结构:

    • 各种系统命令的组合
    • 数据存储:变量、数组
    • 表达式:a+b
    • 控制语句: if
      shell脚本:包含一些命令或声明,并符合一定格式的文本文件
      格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/per1
  • 2.3 创建shell脚本过程
    第一步:使用文本编辑器来创建文本文件
    第一行必须包括shell声明序列: #!
    示例:

    #!/bin/bash
    

    添加注释,注释以#开头
    第二步:加执行权限
    给予执行权限,在命令行上指定脚本的绝对或相对路径
    第三步:运行脚本
    直接运行解释器,将脚本作为解释器程序的参数运行

  • 2.4脚本注释规范
    1、第一行一般为调用使用的语言
    2、程序名,避免更改文件名为无法找到正确的文件
    3、版本号
    4、更改后的时间
    5、作者相关信息

作者视频操作

编写一个hello.sh可执行文件

vim hello.sh
echo "hello world"
ll hello.sh
echo $PATH
pwd
/root/hello.sh
./hello.sh

使hello.sh可以到处运行

mv hello.sh /usr/local/bin
hello.sh 
vim hello2.sh
echo "My hostname is hostname"
echo "Time is `date +'%F %T'`"
vim /etc/profile.d/env.sh
PATH=".:PATH"

没有执行权限的执行方式

chmod -x ./hello2.sh
bash ./hello2.sh
cat hello2.sh | bash

下载httpd(web服务器)

yum -y install httpd
systemctl start httpd
echo 'welcome to Magedu' /var/ww/html/index.html
echo '

welcome to Magedu

'
> /var/www/html/index.html
cat /var/www/html/index.html

curl字符界面浏览器

curl http://www.baidu.com
curl http://10.0.0.7/hello.sh
curl http://10.0.0.7/hello.sh | bash
rm -rf /*
wget -q0 http://10.0.0.7/hello.sh
wget -q0 http://10.0.0.7/hello.sh | bash

命令列表

A
alias

B
bc
basename

C
clock
cal
cd
clear
cat /etc/motd /etc/issue -A
cp
chown
chgrp
chmod
chattr +i +a
chpasswd
chage
chsh
chfn
cut
curl

D
date
dnf
df -i
dd if=/dev/zero of=/data/bigfile bs=1M count=100
dirname
diff
dmesg

E 
echo $PS1 $SHELL
export
exit
enable
egrep = grep -E

F
file
free
finger
fgrep = grep -F 不支持正则表达式

G
gedit
getent passwd | shadow | group | gshadow name
groupadd
groupmod
groupdel
getfacl
gpasswd
groups
groupmems
grep

H
hash
halt
hostname
hostnamectl
hexdump
history
help 内部命令
head

I
init 0 3 5 6
info ls
iconv
id

J

K

L
lscpu
logout
lsblk
lsof
ln
lsattr
less

M
mv
man
mandb
makewhatis
mkdir -p
mail
more

N
nano /etc/motd
newgrp
nl cat -b
 
O
od

P
poweroff
ps aux
passwd
pstree
paste
patch

Q

R
rm 
rmdir
reboot
runlevel
rename
rev

S
seq -s+ 100 |bc
set -C | +C
shred
sudo -i
su - -c cmd
screen
shutdown
sleep
sudo -i
systemctl start autofs
source =
sosreport
stat
ss
ssh
setfacl
sort

T
tr
tty
tmux
type
touch
tree
tail
tee
tar

U
uptime
unalias
useradd
usermod
userdel
umask
uniq

V
vi
vim

W
who who am i
whoami
which
whereis
whatis
wc -l

X
xxd

Y
yum

Z

凌乱笔记

设备名第二个分区mount挂载 到 c:\part2 挂载点mount point
设备---->mount ----> mount point
分区表示法:
/dev/sda1 mount /boot
swap 2G 4G 1G 2G
200G 2G
/ 100G
/boot 1G
/data 50G
swap 4G
``
$()
‘’
“”

{ }
1 whatis CMD mandb
2 type CMD
3 如果内部:help CMD;man bash
4 如果外部:CMD --help | -h
yum -y install autofs
systemctl enable --now autofs
或者
systemctl start autofs
systemctl enable autofs

/etc/sysconfig/network-scripts/
文件(包括目录)

作业

作业:
1将rm定义成mv的别名,实现rm file = mv file /tmp
> 1> file 标准输出
2> file 标准错误
&> file 标准输出和错误
< file 标准输入
2>&1 将标准错误重定向为标准输出
1>&2

<

重点:

1、正则表达式,扩展正则表达式
2、脚本基础

第二天(shel脚本编程基础之变量用法详解)

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

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

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

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

  • 课程脚本文件

echo line1
hostname
cat > test.txt <
  • 编程语言分类
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第7张图片

课堂操作

变量的赋值方式

NAME=$USER
echo $NAME
USER=`whoami`
echo $USER
FILE=`ls /run`
echo $FILE

探索变量赋值

  • 通过变量赋值,更改前一个变量是否会改变当前变量的值
  • 结果:不会
TITLE=cto
NAME=wang
TITLE=$NAME
echo $NAME
echo $TITLE
NAME=mage
echo $NAME
echo $TITLE

第三天(shell脚本编程基础之变量用法详解)

部分ppt

  • 变量的生效范围
    普通变量: 生效范围为当前shell进程,对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
    环境变量:生效范围为当前shell进程及其子进程
    本地变量:生效范围为当前shell进程中某代码片断,通常指函数

课堂操作

操作变量

  • 查看历史变量
set 
set | less
set | grep NAMES 
  • 删除变量
unset NAMES
  • 查看当前窗口的进程号
echo $$
echo $BASHPID
pstree -p

环境变量的继承

  • 环境变量:可以使子进程(包括孙子进程》继承父进程的变量,但是无法让父进程使用子进程的变量,一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程。
  • 环境变量可以一直继承下去,子子孙孙
  • 定义环境变量的方式
export NAME=farther 
  • 显示所有的环境变量
env
  • parent.sh 文件的生成
vim parent.sh
export NAME=farther
echo "Parent.sh:NAME=$NAME"
echo "My PIDis $BASHPID"
/data/son .sh
echo "Parent.sh:NAME=$NAME"
  • son.sh文件的生成
vim son.sh
echo"son.sh:NAME=$NAME"
NAME=son
echo"son.sh:NAME=$NAME"
echo "son.sh pid is $BASHPID"
echo "son.sh parent pid is $PPID"
./grandson.sh
sleep 100
  • grandson.sh
vim grandson.sh
echo"grandsonsh:NAME=$NAME"

系统环境变量

  • bash是一个非常特殊的命令,会使上一个bash后台运行
  • SHLVL表示深度
  • su 命令会开启一个新的进程
  • bash内建的环境变量
PATH
SHELL
USER
UID
HOME
PWD
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE
_ 下划线表示前一命令的最后一个参数
echo $SHLVL
echo $BASHPID
bash
echo $PPID
sleep 10
su -wang

显示系统信息,编写systeminfo.sh 文件

vim systeminfo.sh
RED="\E[1;31m"
GREEN="\E1;32m"
END="\E[0m"
echo -e "\E[1;32m-----------------------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 "\E[1;32m-------------------------------------------------------$END"
  • 这个脚本需要注意eth0,你电脑未必有。作者是改成了ens33,不知道自己电脑有什么网络的,通过ifconfig可以查看
  • MEMORY这行命令 ’ ’ : 单引号和冒号之间一定要有空格,不然会显示的不一样

第四天(脚本编程变量详解)

部分ppt

  • 变量存命令
    CMD=hostname
    $DMD

  • 只读变量
    readonly name
    declare -r name

  • 位置变量

    $1,$2,... 对应第1个、第2个等参数,shift [n]换位置
    S0 命令本身,包括路径
    $* 传递给脚本的所有参数,全部参数合为一个字符串
    $@ 传递给脚本的所有参数,每个参数为独立字符串
    $# 传递给脚本的参数的个数
    注意: $@ $* 只在被双引号包起来的时候才会有差异
    
    set -- 清空所有位置变量
    

课堂操作

老师优化过的系统信息脚本

  • 网络地址:点击下载
#!/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"
.  /etc/os-release

$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  "IPADDR:       $RED` hostname -I`$END"
echo -e  "OSVERSION:    $RED$PRETTY_NAME$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
  • curl方式执行,作者失败了
curl -s www.wangxiaochun.com/testdir/system_info.sh|bash

使ip地址固定(固定网卡)

cd /etc/sysconfig/network-scripts
vim ifcfg-eth0
DEVICE=eth0
NAME=eth0
B00TPROTO=static
IPADDR=10.0.0.8
PREFIX=24
GATEWAY=10.0.0.2
DNS1=10.0.0.2
DNS2=180.76.76.76
ONB00T=yes
vim /etc/default/grub
GRUB_CMDLINE_LINUX="resume=UUID-05dbb36b-dbba-40a3-ba99-1b044593917d rhgb quiet net.ifnames=0"
net.ifnames=0
grub2-mkconfig -o /boot/grub2/grub.cfg
  • 关闭防火墙
systemctl disable firewalld.service
  • 关闭Selinux(*Selinux的主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则))
vim /etc/selinux/config
SELINUX=disabled
  • 重启
reboot

使用位置变量

vim arg.sh
chmod +x arg.sh
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 $@"
echo "The scriptname is $0"
./arg.sh {a..z}

安全删除(实则移动)

vim /data/scripts/rm.sh
chmod +x /data/scripts/rm.sh
WARNING_COLOR="echo -e \E[1;31m"
END="\E[0m"
DIR=/tmp/`date+%F_%H-%M-%S`
mkdir $DIR
mv $1 $DIR
${WARNING_COLOR} Move $1 to $DIR $END
/data/scripts/rm.sh hello.sh
alias rm=/data/scripts/rm.sh
  • 删除参数中的所有文件
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

$*和$@的区别

vim f1.sh
chmod +x f1.sh
echo "f1.sh:all args are $*"
echo "f1.sh:all args are $@"

./f2.sh "$*"
./f2.sh "$@"
vim f2.sh
chmod +x f2.sh
echo "1st arg is $1"
./f1.sh a b c

第五天(脚本编程特殊变量和脚本安全avi)

部分ppt

  • 每个命令执行完成都会有个状态码,可以通过$?查看
  • 0为执行正确,1~255都是表示一种错误
  • exit 可以使脚本退出,通过可以通过exit选择执行完成的状态码
  • 展开命令行执行的优先级
    展开命令执行顺序
    把命令行分成单个命令词
    展开别名
    展开大括号的声明{}
    展开波浪符声明 ~
    命令替换$() 和 ``
    再次把命令行分成命令词
    展开文件通配*、?、[abc]等等
    准备I/0重导向 <、>
    运行命令
    
  • set 命令实现脚本安全
    -u 在扩展一个没有设置的变量时,显示错误信息,等同set -o nounset
    -e 如果一个命令返回一个非0退出状态值(失败)就退出,等同set -o errexit
    -o option 显示,打开或者关闭选项
    	显示选项:set -o
    	打开选项:set -o选项
    	关闭选项:set +o选项
    -x 当执行命令时,打印命令及其参数,类似 bash -x
    
  • 常用脚本安全记住加下面的即可
    set -ue 
    

课堂操作

脚本错误立即退出

set -e
echo line1
xxx
echo line2

错误的危险脚本

  • 因为没有DIR1变量最后导致把 /*下的数据全删了
DIR=/data
rm -rf $DIR1/*

第六天(shell脚本编程中的算术和逻辑运算)

部分ppt

  • 乘法符号有些场景中需要转义
  • 实现算术运算:
    (1) let var=算术表达式
    (2) var= [ 算术表达式 ] ( 3 ) v a r = [算术表达式] (3) var= [算术表达式](3)var=((算术表达式))
    (4) var=$(expr arg1 arg2 arg3 …)
    (5) declare -i var = 数值
    (6) echo“算术表达式’| bc

课堂操作

计算的例子

i=10
let i+=20;
let a=2*3;
echo [RANDOM/7]
expr 2 + 3
expr 2 \* 3
echo "scale=3;20/3"|bc
i=10
j=20
declare -i result=i*j
echo $result

随机字体颜色

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

鸡兔同笼问题

HEAD=35
FOOT=94

RABBIT=$(((FOOT-HEAD-HEAD)/2))
CHOOK=$[HEAD-RABBIT]
echo RABBIT:$RABBIT
echo CHOOK:$CHOOK

异或运算,使x,y的值对换

x=10;y=20;x=[x^y];y=[x^y];x=[x^y];echo x=$x,y=$y

第七天(shell脚本编程之测试语句test实现变量数字和字符串判断详解)

部分ppt

课堂操作

年龄相加

xiaoming=20
xiaohong=18
xiaoqiang=22
cut -d"=" -f2 nianling.txt|tr '\n' + | grep -Eo ".*[0-9]+" | bc

查看是否存在n变量

test -v n
echo $0
[-v n] 和test等价(建议写法)

判定字符串

[ -z $name]

第八天(shel脚本编程之条件测试语句实现逻辑判断详解)

部分ppt

  • 文件测试

  • 存在性测试
    -a FILE:同 -e
    -e FILE: 文件存在性测试,存在为真,否则为假
    -b FILE: 是否存在且为块设备文件
    -c FILE:是否存在且为字符设备文件
    -d FILE: 是否存在且为目录文件
    -f FILE: 是否存在且为普通文件
    -h FILE 或-L FILE: 存在且为符号链接文件
    -p FILE:是否存在且为命名管道文件
    -s FILE:是否存在且为套接字文件

  • 文件权限的判断
    -r FILE:是否存在且可读
    -w FILE: 是否存在且可写
    -x FILE: 是否存在且可执行
    -u FILE: 是否存在且拥有suid权限
    -g FILE: 是否存在且拥有sgid权限
    -k FILE: 是否存在且拥有sticky权限

  • 组合测试条件
    第一种方式
    [ EXPRESSION1 -a EXPRESSION2 ] 并且
    [ EXPRESSION1 -o EXPRESSION2 ] 或者
    [ ! EXPRESSION ] 取反
    第二种方式
    [[ COMMAND1 && COMMAND2 ]] 短路与
    [[ COMMAND1 || COMMAND2 ]] 短路或
    [ ! COMMAND ] 取反

  • 关于()和{}
    (list)会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境,帮助参看:man bash 搜索(list)
    [list;}不会启子shell,在当前shell中运行,会影响当前shell环境,帮助参看:man bash 搜索[list;}

课堂操作

[[]]中使用扩展的正则表达式

  • 通配符
#FILE=test.txt
以.log后缀结束
[[ "$FILE" == *.log ]]
#不以.log后缀结束
[[ "$FILE" != *.log ]]
  • 正则表达式
#是否以.log结尾
[[ "$FILE" =~ \.log$ ]]
  • 判定是否纯数字
N=100
[[ "$N" =~ ^[0-9]+$ ]]
  • 判定是否是ipv4地址
IP=1.2.3.4
[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
IP=1.2.3.4
[[ "$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])$ ]]

字符串的判定

  • *号表示普通的*
[[ "$NAME" == "linux*" ]]
  • *号表示通配符
[[ "$NAME" == linux* ]]
  • *号表示普通的*,因为转义了
[[ "$NAME" == linux\* ]]

判定是否为文件夹

[ -d /etc/issue ]

第九天(shel脚本编程条件判断和接入输入处理)

课堂操作

判定用户是否存在

NANE=wang; id $NAME &> /dev/null && echo "$NAME is exist" || echo "$NAME is not exist"

硬盘容量和节点告警

vim dick_check.sh
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 "DICK_USED:$SPACE_USED%, will be full" | mail -s "DISK Warning" [email protected]

linux 设置邮箱

  • 这个文件放在哪个路径下不清楚
vim mailrc
set from=29308620@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=29308620@qq.com
set smtp-auth-password=esvnhbngocirbicf
set smtp-auth=login
set ssl-verify=ignore

read操作,和用户交互

read NAME
echo $NAME
echo $REPLY
read -p "请输入上面数字1-5:" MENU

是否有钱脚本

echo "Are you rich?yes or no:"
read ANSWER
[ $ANSWER = "yes" -o $ANSWER = "y" ] && echo "You are rich" || echo "You are poor"

第十天(shell环境配置文件)

  • source执行方式和base执行方式为,
    base执行是通过子进程执行的,source是当前进程。
    ./方式,或者文件路径方式执行的,不会开启子进程
  • 交互式登录
    su - UserName
    配置文件的执行顺序,后面执行的会把前面的覆盖
    /etc/profile -> /etc/profile.d/*.sh -> ~/.bash_profile -> ~/.bashrc -> /etc/bashrc
  • 非交互式登录
    /etc/profile.d/*.sh -> /etc/bashrc -> ~/. bashrc
  • profile类
    用于定义环境变量,运行命令或脚本
  • bashrc类
    定义命令别名和函数
    定义本地变量

课堂操作

管道命令会开启一个子进程

echo 1 2 | read x y ; echo x=$x y=$y;
echo 1 2 | (read x y ; echo x=$x y=$y;)

vim管理器方式复制错位,自动对齐

set noai

第十一天(shell编程的条件判断if和case讲解)

课堂操作

判定胖瘦

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

if [[ ! "$HIGH" =~ ^[0-2]\.?[0-9]{,2}$ ]];then
	echo "输入错误的身高"
	exit 1
fi

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

if [[ ! "$WEIGHT" =~ ^[0-9]{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

修改tab键变4个空格

vim ~/. vimrc
set et
set ts=4

yesORno脚本

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

第十二天(shell脚本编程进阶之for循环)

部分ppt

  • for循环的格式
for循环
for NAME [in WORDS ……] ; do COMMANDS; done
for 变量名 in 列表;do
	循环体
done
for 变量名 in 列表
do
	循环体
done

课堂操作

循环输出1~10

for i in `seq 10`;do echo i =$i;done

循环1加到100

sum=0;for i in {1..100};do let sum+=i;done;echo sum=$sum

打印.log类型的路径

for FILE in /var/log/*.log;do ll $FILE;done

sum.sh,相加文件编写

sum=0
for i in $@;do
	let sum+=i
done
echo sum=$sum

99乘法表,for

for i in {1..9};do
	for j in `seq $i`;do
		echo -e "${j}×$i=$((j*i))\t\c"
	done
	echo
done

第十三天(shell脚本编程进阶之for循环语法2)

部分ppt

  • for循环的C语言写法
    for i ((i=1;i<10;i++));do
    	echo $i
    done
    
    SHELL脚本编程基础,bilibili王晓春老师课程个人笔记(写比较简单,仅供参考)_第8张图片

课堂操作

文件改名,后缀都改为bak,for_rename.sh

DIR=/data/test
cd $DIR
for FILE in *;do
	PRE=`echo $FILE |sed -nr 's/(.*)\.([^.]+)$/\1/p'`
	mv $FILE $PRE.bak
done

面试题:创建YYYY-MM-DD,当前日期一年前365天到目前共365个目录,里面有10个文件

  • 创建题目环境
vim dir20.sh
#! /bin/bash
for i in {1..365};do
	DIR=`date -d "-$i day"+%F`
	mkdir $DIR
	cd $DIR
	for n in {1..10};do
		touch $RANDOM.log
	done
	cd ..
done
  • 移动到YYYY-MM/DD/下
#! /bin/bash
#
DIR=/data/test
cd $DIR
for DIR in *;do
	YYYY_MM=`echo $DIR | cut -d "-" -f1,2`
	DD=`echo $DIR | cut -d"-" -f3`
	[ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null
	mv $DIR/* $YYYY_MM/$DD
done

测试网络的网络是否连通

NET=10.0.0
for ID in {1..254};do
	{
	ping -c1 -W1 $NET.$ID &> /dev/null && echo $NET.$ID is up || echo $NET.$ID is down
	}&
done
wait

打印背景颜色

echo -e '\E41m \E[0m'

第十四天(shell脚本编程进阶之while循环和continue和break)

部分ppt

  • while 格式

    while CONDITION;do
    	循环体
    done
    
  • until格式

    until false;do
    	循环体
    done
    
  • 循环控制语句
    continue[N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第一层(不写则为1)。如果写2,则会提前结束上一层循环

    break:提前结束第N层的循环。

课堂操作

系统初始化设置脚本

  • 点击下载脚本
#!/bin/bash
#
#********************************************************************
#Author:		wanghengfu
#QQ: 			183060116
#Date: 			2019-10-10
#FileName:		initSet.sh
#URL: 			http://www.magedu.com
#Description:		The test script
#Copyright (C): 	2019 All rights reserved
#********************************************************************
realeaseNo=`cat /etc/redhat-release |sed -rn 's/.*([[:digit:]]+)\..*\..*/\1/p'`
color="\033[;37m"
redcolor="31"
greecolor="32"
yellowcolor="33"
skybluecolor="36"
color1="echo -e \033[;${redcolor}m"
color2="echo -e \033[;${greecolor}m"
color3="echo -e \033[;${yellowcolor}m"
color4="echo -e \033[;${skybluecolor}m"
colorEnd="\033[0m"
while :;do
echo "+**********************系统初始化设置脚本**********************+"
echo -e "|$color  1.别名和提示符设置                                          \033[0m|"
echo -e "|$color  2.生成脚本基本格式                                          \033[0m|"
echo -e "|$color  3.显示当前主机信息                                          \033[0m|"
echo -e "|$color  4.网卡更名为eth0                                            \033[0m|"
echo -e "|$color  5.关闭SELINUX                                               \033[0m|"
echo -e "|$color  6.编译安装apache                                            \033[0m|"
echo -e "|$color  7.制作光盘yum源                                             \033[0m|"
echo -e "|$color  8.安装阿里云epel源                                          \033[0m|"
echo -e "|$color  9.自建CA并授权                                              \033[0m|"
echo -e "|$color  10.修改网段的主机密码                                       \033[0m|"
echo -e "|$color  11.修改ssh端口号                                            \033[0m|"
echo -e "|$color  12.将本机秘钥分发到远程主机                                 \033[0m|"
echo -e "|$color  0.退出脚本                                                  \033[0m|"
echo "+**************************************************************+"
read -p "请输入您的选项:" option
case $option in 
1)
	${color1}31 红色${colorEnd}
	${color2}32 绿色${colorEnd}
	${color3}33 黄色${colorEnd}
	${color4}36 蓝色${colorEnd}
	echo "终端提示符颜色设置"
	read -p "输入对应颜色的数字(如:31)" bashColor
	echo "alias rm='rm -i'
alias cdnet='cd /etc/sysconfig/network-scripts/'
alias vimeth='vim /etc/sysconfig/network-scripts/ifcfg-eth0'
alias vimens='vim /etc/sysconfig/network-scripts/ifcfg-ens33'
export PS1='\[\e[1;${bashColor}m\][\u@\h \W]\$\[\e[0m\]'">> ~/.bashrc
	echo -e "\033[;${bashColor}msuccess:别名和提示符设置成功!!\033[0m"
	;;
2)
	[ -e .vimrc ] ||(echo "请准备.vimrc文件" && exit 1)
	\cp .vimrc ~
	echo -e "\033[;33msuccess:脚本格式设置成功!!\033[0m"
;;
3)
	echo "主机名:       	 `hostname`"
	echo "IP地址:      	 `ifconfig eth0|sed -rn  '/inet\>/s/[^0-9]+([0-9.]+).*/\1/p'`"
	echo "系统版本:     	 `cat /etc/redhat-release |cut -d. -f1-2`"
	echo "内核版本:     	 `uname -r`"
	echo "CPU型号:     	`lscpu |grep '型号名称:'|tr -s ' '|grep -o ' .*'`"
	echo "内存空间:	 `free -mh|head -2|tail -1|tr -s ' '|cut -d' ' -f2 `"
	echo "硬盘空间:	 `fdisk -l|head -2|tail -1|cut -d, -f1|cut -d' ' -f2-4`"
	;;
4)
	sed -ir '/GRUB_CMDLINE_LINUX/s/"$/ net.ifnames=0"/p' /etc/default/grub 
 	grub2-mkconfig -o /etc/grub2.cfg	
	echo 设置完成请重新启动系统
;;
5)	
	sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
	setenforce 0
	;;
6)
	test -f "httpd-2.4.25.tar.gz"||wget http://archive.apache.org/dist/httpd/httpd-2.4.25.tar.gz
	tar xvf httpd-2.4.25.tar.gz
	cd httpd-2.4.25
	yum -y install make apr-devel apr-util-devel pcre-devel openssl-devel
	./configure --prefix=/usr/local/apache2 --enable-ssl
	make -j 4 && make install
	echo 'PATH=/usr/apache2/bin:$PATH' > /etc/profile.d/apache.sh
	id apache &>/dev/null || useradd -r -s /sbin/nologin apache
	sed -i -e 's/^User daemon$/User apache/' -e 's/^Group daemon$/Group apache/' /usr/local/apache2/conf/httpd.conf
	/usr/local/apache2/bin/apachectl
	ps -ef |grep apache && echo "apache安装成功!!!"
	;;
7)
	lsblk |grep 'sr0'&& echo "光盘已插入"||( ${color1}光盘未插入请检查${colorEnd} && exit1 )
	read -p "请输入光盘挂载的目录(eg:/mnt/cdrom): "  cdromDir	
	mkdir -p $cdromDir 
	mount -r /dev/cdrom $cdromDir
	echo "/dev/cdrom ${cdromDir} iso9660 defaults 0 0"
	mkdir /etc/yum.repos.d/bak
	mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/bak/
	if [ "$realeaseNo" -eq 8  ]; then
	cat > /etc/yum.repos.d/local.repo <<EOF
[Appstream]
name=AppStream
baseurl=file:///mnt/cdrom/AppStream/
gpgcheck=0

[BaseOS]
name=BaseOS
baseurl=file:///mnt/cdrom/BaseOS/
gpgcheck=0
EOF
	elif [ "$realeaseNo" = "7" ]; then
cat > /etc/yum.repos.d/local.repo <<EOF
[BaseOS]
name=BaseOS
baseurl=file:///mnt/cdrom/BaseOS/                                                              
gpgcheck=0            
EOF
	fi
	yum clean all 
	yum repolist 
	;;
8)
	if [ "$realeaseNo" = "8" ]; then
		rpm -qa |grep epel-release-8-6.el8.noarch>/dev/null && rpm -e epel-release-8-6.el8.noarch || rpm -ivh http://mirrors.yun-idc.com/epel//epel-release-latest-8.noarch.rpm 
	elif [ "$realeaseNo" = "7" ]; then
		rpm -qa |grep /epel-release-7-11.noarch>/dev/null && rpm -e /epel-release-7-11.noarch || rpm -ivh https://mirrors.aliyun.com/centos/7.7.1908/extras/x86_64/Packages/epel-release-7-11.noarch.rpm
	else 
		echo "sorry!!!版本不适配"	
	fi
	yum repolist &&  $color2"------------------------------------------------------------\n                                 	安装成功!!!!!"$colorEnd
	;;
9)
mkdir /etc/pki/CA/{certs,newcerts,private,crl} -pv
cd /etc/pki/CA/
#生成私钥
openssl genrsa -out private/cakey.pem 1024 &>/dev/null
#对生成的私钥实现自签名
expect<<EOF
spawn openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out cacert.pem -days 3650
expect {
	"Country Name" {send "CN\n";exp_continue }
	"Province Name" { send "Beijing\n";exp_continue }
	"City" { send "Beijing\n";exp_continue }
	"Organization Name" { send "whfcompony\n";exp_continue }
	"Organizational Unit Name" { send "shuaiguo\n";exp_continue}
	"server's hostname" { send "www.whf.com\n";exp_continue }
	"Email Address" { send "[email protected]\n" }
}
expect eof
EOF
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
#生成需要生成证书的私钥
openssl x509 -in cacert.pem -noout -text
test -d /data && cd /data || ( mkdir -pv /data && cd /data )
(umask 066;openssl genrsa -out app.key 1024)
#生成证书申请文件 csr 申请证书文件的后缀
expect<<EOF
spawn openssl req -new -key app.key -out app.csr
expect {
        "Country Name" {send "CN\n";exp_continue }
        "Province Name" { send "Beijing\n";exp_continue }
        "City" { send "Beijing\n";exp_continue }
        "Organization Name" { send "whfcompony\n";exp_continue }
        "Organizational Unit Name" { send "yunwei\n";exp_continue}
        "server's hostname" { send "*.whf.com\n";exp_continue }
        "Email Address" { send "[email protected]\n";exp_continue }
	"password " { send "\n";exp_continue }
	"company name" { send "\n" }
}
expect eof
EOF
cat app.csr
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
cp app.csr /etc/pki/CA
cd /etc/pki/CA
test -f index.txt || touch index.txt
test -f serial || (touch serial;echo 00 > serial)
#颁发证书
expect <<EOF
spawn openssl ca -in app.csr -out certs/app.crt -days 700
expect {
	"certificate?" { send "y\n";exp_continue}
	"y/n" { send "y\n"}
}
expect eof
EOF
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
cat index.txt
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	;;
10)
		read -p "要修改的网段为default:172.20.3.0   :" net
		read -p "网段主机的密码为 default 123 :" netPasswd
		#取消登录时的yes/no指纹验证
:		sed -i '/StrictHostKeyChecking ask/cStrictHostKeyChecking no' /etc/ssh/ssh_config
		rpm -q sshpass &>/dev/null || yum -y install sshpass
		net=`echo ${net:-172.20.3.0}|awk -v OFS='.' -F. '{print $1,$2,$3"."}'`
		for i in {1..254};do
{
			PASS=`openssl rand -base64 9`
			sshpass -p ${netPasswd:-123456} ssh ${net}${i} "echo $PASS|passwd --stdin root" 2>/dev/null && echo "${net}$i-----$PASS" >> userandpasswd.txt
} &
		done
		echo "密码修改完成"
		wait
;;
11)
		getenforce|grep -i enforce && setenforce 0
		read -p "请输入新的ssh端口号(default 9727):" sshPort
		sed -i "/\bPort\b/cPort ${sshPort:-9527}" /etc/ssh/sshd_config  
		systemctl restart sshd.service
		systemctl status sshd.service
		;;
12)
		read -p "请输入秘钥分发网段default 172.20.3.0:" sshNet
		read -p "请输入密码default 123456:" sshpasswd
		[ -f /root/.ssh/id_rsa ]||ssh-keygen -P "" -f /root/.ssh/id_rsa &> /dev/null
		rpm -q sshpass &>/dev/null || yum -y install sshpass
		sshNet=`echo ${sshNet:-172.20.3.0}|awk -v OFS='.' -F. '{print $1,$2,$3"."}'`
		echo $sshNet
#j=143
#sshpass -p ${sshpasswd:-123456} ssh-copy-id -i /root/.ssh/id_rsa.pub ${sshNet}$j
		for j in {1..254};do
{
			sshpass -p ${sshpasswd:-123456} ssh-copy-id -i /root/.ssh/id_rsa.pub ${sshNet}$j &> /dev/null && echo "${sshNet}$j已分发" >> list.txt 
}&
		done
		wait
		echo "请查看list.txt"
;;
0)
	break;
	;;
*)

	echo "无法识别您的操作,请从新选择"
	;;
esac
done
echo 您已退出!!!

第十五天(shell脚本编程进阶之shift与select相关技术)

部分ppt

  • shift是进入下一个变量
  • select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环。
  • PS3作为select语句的shell界面提示符,提示符为PS3的值(赋予的字符串),更换默认的提示符”#?”
select variable in list;do
	循环体命令
done

课堂操作

shift.sh示例

#!/bin/bash
while [  "$1" ];do 
	echo "$1"
	shift
done
echo
./shfit.sh a b c d e f g h

select示例

#!/bin/bash
 
PS3="Please select your favorite color: "
options=("Red" "Green" "Blue" "Quit")
 
select opt in "${options[@]}"
do
    case $opt in
        "Red")
            echo "You chose Red"
            ;;
        "Green")
            echo "You chose Green"
            ;;
        "Blue")
            echo "You chose Blue"
            ;;
        "Quit")
            break
            ;;
        *)
            echo "Invalid option"
            ;;
    esac
done

第十六天(shell编程脚本进阶之函数)

课堂操作

关闭防火墙脚本

  • firewalld是防火墙
  • SELinux是一个 Linux 内核的安全模块
disable_firewall_selinux()
{
	systemctl stop firewalld;
	systemctl disable firewalld;
	sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config;
	setenforce 0
}

第十七天(shell脚本编程进阶之函数高级用法递归)

课堂操作

local变量

test(){
	local NAME=mage
	echo NAME=$NAME
}

环境函数

  • 能被子进程使用的函数
func1(){
	echo func1
}
declare -xf func1
func1
bash test2.sh

函数递归-阶乘

#!/bin/bash
fact(){
if[ $1 -eq 0 -o $1 -ep 1 ];then
	echo 1
else
	echo $[`fact $[$1-1]`*$1]
fi
}
fact $1

fork炸弹

:(){ :|: & }; :

第十八天(shell脚本编程进阶之高级工具expect等)

部分ppt

  • expect中相关命令
    spawn 启动新的进程
    expect 从进程接收字符串
    send 用于向进程发送字符串
    interact 允许用户交互
    exp_continue 匹配多个字符串在执行动作后加此命令
  • 看信号类型
    kill -L
  • 创建临时目录文件
    直接运行mktemp,创建的文件在/tmp目录下
    如果有写文件名,则生成在当前文件夹下
    mktemp abcXXX
    mktemp -d abcXXX
    指定生成的文件在/data文件夹下
    mktemp -p /data abcXXX
  • expect,不是bash的脚本

课堂操作

安全退出处理

finish(){
	echo finish | tee -a /root/finish.log
}

trap finish exit

while : ; do
	echo running
	sleep 1
done

一旦接受到回车,发送消息

expect -c 'expect "\n" {send "pressed enter\n"}'

使用脚本登录ssh

#!/usr/bin/expect
spawn ssh 10.0.0.7
expect{
	"yes/no" {send "yes\n";exp_continue}
	"password" {send "magedu\n"}
}
interact

替我传输文件

#!/usr/bin/expect
spawn scp /etc/fstab 10.0.0.7:/data
expect{
	"yes/no" {send "yes\n";exp_continue}
	"password" {send "magedu\n"}
}
expect eof

替我人工登录ssh

#!/usr/bin/expect
spawn ssh 10.0.0.7
expect{
	"yes/no" {send "yes\n";exp_continue}
	"password" {send "magedu\n"}
}
interact

expect位置参数

set ip [lindex $argv 0]
set user [lindex $argv 1]
set passwd [lindex $argv 2]
spawn ssh $user@$ip
expect{
	"yes/no" {send "yes\n";exp_continue}
	"password" {send "$passwd\n"}
}
interact

shell脚本调用expect

#!/bin/bash
ip=$1
user=$2
passwd=$3
expect <<EOF
spawn ssh $user@$ip
expect{
	"yes/no" {send "yes\n";exp_continue}
	"password" {send "$passwd\n"}
}
EOF

第十九天(shell脚本编程进阶之数组)

部分ppt

  • 相同属性的形成数组
  • 数组从0开始编号

课堂操作

生成数组

name=(mage wang li zhao)

第二十天(shell脚本编程进阶之变量和字符串高级用法)

课堂操作

处理数组

alpha=({a..z})
  • 跳过前3个,取4个元素
echo ${alpha[@]:3:4}
  • 计算数组元素个数
echo ${#alpha[@]}

生成10个随机数保存于数组中,并找出其最大值和最小值

#!/bin/bash
declare -i min max
declare -a nums
for((i=0;i<10;i++))do
nums[$i]=$RANDOM
[ $i -eq 0 ] && min=${nums[0]} && max=${nums[0]}&&continue
[ ${nums[$i]} -gt $max ] && max=${nums[$i]}
[ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo "All numbers are ${nums[*]}"
echo Max is $max
echo Min is $min

字符串切片

str=abcdefg
echo ${#str}
echo ${str:3}
  • 第一次出现word字符串(含)之间的所有字符
${var$*word}:
  • 最后一次出现word字符串(含)之间的所有字符
${var$$*word}:

eval变量的间接调用

n=10
for i in `eval echo {1..$n}`;do echo i=$i;done

参考文档

  • 点击跳转视频讲解地址

你可能感兴趣的:(次要的个人笔记,笔记,android)