Shell脚本编程
Shell基础
编程语言排名链接
https://www.tiobe.com/tiobe-index/
TIBOE 2024 年 7 月的最新编程语言流行度排名
格式要求:首行shebang机制,即:
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
shell脚本注释规范
- 第一行一般为调用使用的语言
- 程序名,避免更改文件名为无法找到正确的文件
- 版本号
- 更改后的时间
- 作者相关信息
- 该程序的作用,及注意事项
- 最后是各版本的更新简要说明
为方便在创建sh脚本时自动创建脚本注释,可以在/etc/vimrc
配置文件末尾添加如下配置,使用vim编辑器时会自动调用该配置
set shiftwidth=4
set ts=4
set expandtab
set ignorecase
autocmd BufNewFile *.sh exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,"#")
call setline(3,"#******************************************************************")
call setline(4,"#Filename: ".expand("%"))
call setline(5,"#Version: 1.0")
call setline(6,"#Date: ".strftime("%Y-%m-%d"))
call setline(7,"#Author: yoob")
call setline(8,"#Email: chenyongq99@163.com")
call setline(9,"#Website: http://www.yoob.com")
call setline(10,"#Description: The test script")
call setline(11,"#Copyright (C) ".strftime("%Y")." All rights reserved")
call setline(12,"#*****************************************************************")
call setline(13,"")
endif
endfunc
autocmd BufNewFile * normal G
这里创建一个测试脚本**test.sh**
#!/bin/bash
#
#******************************************************************
#Filename: test.sh
#Version: 1.0
#Date: 2024-07-23
#Author: yoob
#Email: chenyongq99@163.com
#Website: http://www.yoob.com
#Description: The test script
#Copyright (C) 2024 All rights reserved
#*****************************************************************
echo 'test'
本地执行shell的五种方法
bash test.sh //脚本作为参数给到bash解释器,不用添加执行权限,不用添加shebang
sh test.sh //脚本作为参数给到sh解释器,不用添加执行权限,不用添加shebang
/opt/myShell/test.sh //绝对路径,要添加执行权限和头部shebang,否则找不到解释器路径
./myShell/test.sh //相对路径,要添加执行权限和头部shebang,否则找不到解释器路径
test.sh //直接执行,要添加$PATH路径'export PATH=/opt/myShell'
. test.sh //直接在当前环境进程中执行,会影响当前环境变量,执行脚本慎用!!!!!
本地执行url远程脚本
curl http://10.0.0.171/myShell/test.sh //打印远程脚本
curl http://10.0.0.171/myShell/test.sh | bash //bash解释器执行远程脚本
shell脚本调试三种错误
- 语法错误
- 命令错误
- 逻辑错误
bash -n setEth0.sh //发现语法错误
bash -x setEth0.sh //发现命令错误,和逻辑错误
语法基础
SHELL变量
查看进程
pstree -p //查看进程树
echo $BASHPID //查看bash进程id
变量赋值及引用
NAME='zhang' //赋值时不能有空格,等价NAME=zhang
NAME+=san //字符串追加
NAME='whoami' //赋值命令字符串
echo `$NAME` //调用时执行,等价$NAME
NAME=`whoami` //赋值命令执行结果
echo $NAME //此时变量已经为命令执行结果
变量打印与删除
unset
$ \textcolor{red}{不带变量名称时,会默认删除所有变量} $
set //打印所有变量
unset -v NAME NAME1 //仅删除指定变量
unset -f function_name //仅删除函数
环境变量的声明与赋值,修改
export NAME=yoob //声明与赋值,在当前shell和子shell中都可用
declare -x NAME=yoob //同上
export PATH=/opt/myShell:$PATH //变量修改
查看指定进程/进程的环境变量
- 注意,该变量是指环境变量,不是脚本的局部变量
export
和env
的不同在于,env命令主要用于显示所有环境变量,而export命令主要用于设置环境变量并将它们传递给子进程
export //查看当前shell进程的环境变量
env //同上
cat /proc/$PID/environ | tr '\0' '\n' //格式化打印指定进程的环境变量
只读变量,即常量
- 只读常量无法删除,通过
exit
退出当前进程来删除常量
readonly PI=3.14 //只读常量声明赋值
declare -r PI=3.14 //同上
exit
位置变量
- 在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
$0 命令本身,包括路径
$* 传递给脚本的所有参数,全部参数合为一个字符串
$@ 传递给脚本的所有参数,每个参数为独立字符串
$# 传递给脚本的参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异
set -- //清空所有位置变量
rm删除的安全实现
- 使用mv移动代替删除,防止误删
#!/bin/bash
# ------------------------------------------
# Filename: rm.sh
# Version: 1.0
# Date: 2023/12/20
# Author: yoob
# Email: chenyongq99@163.com
# Website: null
# Description: This is the first script for remove file
# Copyright: 2023 yoob
# License: GPL
# ------------------------------------------
WARNING_COLOR="echo -e \033[0;31m"
END="\033[0m"
DIR="/tmp/$(date +%F_%H-%M-%S)"
mkdir -p $DIR
mv $* $DIR
${WARNING_COLOR}Move $* to $DIR $END
退出状态码变量
注意:
- 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
- 如果exit后面无数字,终止退出状态取决于exit命令前面命令执行结果
- 如果没有exit命令, 即未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后 一条命令的状态码
$?的值为0 #代表成功
$?的值是1到255 #代表失败
exit [n] #自定义退出状态码
set命令实现脚本安全
set -u #等同set -o nounset,在扩展一个没有设置的变量时,显示错误信息
set -e #等同set -o errexit,如果一个命令返回一个非0退出状态值(失败)就退出
set -o #查看选项
格式化输出printf
常用格式替换符
说明:
- %#s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字符宽,- 表示 左对齐
- %03d 表示3位宽度,不足前面用0补全,超出位数原样输出
- %.2f 中的2表示小数点后显示的小数位数
替换符 | 功能 |
---|---|
%s | 字符串 |
%d,%i | 十进制整数 |
%f | 浮点格式 |
%c | ASCII字符,即显示对应参数的第一个字符 |
%b | 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转 义 |
%o | 八进制值 |
%u | 不带正负号的十进制值 |
%x | 十六进制值(a-f) |
%X | 十六进制值(A-F) |
%% | 表示%本身 |
常用转义字符
转义符 | 功能 |
---|---|
\a | 警告字符,通常为ASCII的BEL字符 |
\b | 后退 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ | 表示\本身 |
SHELL运算
算数运算
- 主意:bash只支持整数,不支持小数
算数运算符号
* / % multiplication, division, remainder, %表示取模,即取余数,示例:9%4=1,5%3=2
+ - addition, subtraction
i++ i-- variable post-increment and post-decrement
++i --i variable pre-increment and pre-decrement
= *= /= %= += -= <<= >>= &= ^= |= assignment
- + unary minus and plus
! ~ logical and bitwise negation
** exponentiation 乘方,即指数运算
<< >> left and right bitwise shifts
<= >= < > comparison
== != equality and inequality
& bitwise AND
| bitwise OR
^ bitwise exclusive OR
&& logical AND
|| logical OR
expr?expr:expr conditional operator
expr1 , expr2 comma
实现算数运算
常用$[表达式]
(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
示例:var=$[RANDOM%10+11] #取11-20的随机数
范例:今有雉兔同笼,上有三十五头,下有九十四足,问雉兔各几何?
鸡兔同笼,是中国古代著名典型趣题之一,记载于《孙子算经》之中。
#!/bin/bash
HEAD=$1
FOOT=$2
RABBIT=$(((FOOT-HEAD-HEAD)/2))
CHOOK=$[HEAD-RABBIT]
echo RABBIT:$RABBIT
echo CHOOK:$CHOOK
逻辑运算
与&
0 与 0 = 0
0 与 1 = 0
1 与 0 = 0
1 与 1 = 1
或|
0 或 0 = 0
0 或 1 = 1
1 或 0 = 1
1 或 1 = 1
非!
! 1 = 0 ! true
! 0 = 1 ! false
异或^
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
范例:变量互换
[root@centos8 ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
x=20,y=10
[root@centos8 ~]#x=10;y=20;x=$[x^y];y=$[x^y];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 必须要参与运算,才能得到最终的结果
条件测试命令
条件测试命令
- test EXPRESSION
- [ EXPRESSION ] #和test 等价,建议使用 [ ]
- [[ EXPRESSION ]] 相关于增强版的 [ ], 支持[]的用法,且支持扩展正则表达式和通配符
主意:EXPRESSION前后必须有空白字符
[root@localhost myShell]# help test
test: test [expr]
Evaluate conditional expression.
Exits with a status of 0 (true) or 1 (false) depending on
the evaluation of EXPR. Expressions may be unary or binary. Unary
expressions are often used to examine the status of a file. There
are string operators and numeric comparison operators as well.
The behavior of test depends on the number of arguments. Read the
bash manual page for the complete specification.
File operators:
-a FILE True if file exists.
-b FILE True if file is block special.
-c FILE True if file is character special.
-d FILE True if file is a directory.
-e FILE True if file exists.
-f FILE True if file exists and is a regular file.
-g FILE True if file is set-group-id.
-h FILE True if file is a symbolic link.
-L FILE True if file is a symbolic link.
-k FILE True if file has its `sticky' bit set.
-p FILE True if file is a named pipe.
-r FILE True if file is readable by you.
-s FILE True if file exists and is not empty.
-S FILE True if file is a socket.
-t FD True if FD is opened on a terminal.
-u FILE True if the file is set-user-id.
-w FILE True if the file is writable by you.
-x FILE True if the file is executable by you.
-O FILE True if the file is effectively owned by you.
-G FILE True if the file is effectively owned by your group.
-N FILE True if the file has been modified since it was last read.
FILE1 -nt FILE2 True if file1 is newer than file2 (according to
modification date).
FILE1 -ot FILE2 True if file1 is older than file2.
FILE1 -ef FILE2 True if file1 is a hard link to file2.
String operators:
-z STRING True if string is empty.
-n STRING
STRING True if string is not empty.
STRING1 = STRING2
True if the strings are equal.
STRING1 != STRING2
True if the strings are not equal.
STRING1 < STRING2
True if STRING1 sorts before STRING2 lexicographically.
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
Other operators:
-o OPTION True if the shell option OPTION is enabled.
-v VAR True if the shell variable VAR is set
! EXPR True if expr is false.
EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.
EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.
arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne,
-lt, -le, -gt, or -ge.
Arithmetic binary operators return true if ARG1 is equal, not-equal,
less-than, less-than-or-equal, greater-than, or greater-than-or-equal
than ARG2.
Exit Status:
Returns success if EXPR evaluates to true; fails if EXPR evaluates to
false or an invalid argument is given.
判断操作系统
. /etc/os-release
[ $ID = 'centos' ]
echo $?
变量测试
#判断 NAME 变量是否定义
[ -v NAME ]
#判断 NAME 变量是否定义并且是名称引用,bash 4.4新特性
[ -R NAME ]
数值测试
-eq 是否等于
-ne 是否不等于
-gt 是否大于
-ge 是否大于等于
-lt 是否小于
-le 是否小于等于
#示例:
i=10; j=7; [ $i -eq $j ]; echo $?
算数表达式比较
== 相等
!= 不相等
<=
>=
<
>
字符串测试
建议:当使用正则表达式或通配符使用[[ ]],其它情况一般使用 [ ]
结论:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*, 需要加“” 或转义
- test和 [ ]用法
test和 [ ]用法
-z STRING 字符串是否为空,没定义或空为真,不空为假,
-n STRING 字符串是否不空,不空为真,空为假
STRING 同上
STRING1 = STRING2 是否等于,注意 = 前后有空格
STRING1 != STRING2 是否不等于
> ascii码是否大于ascii码
< 是否小于
- [[]] 用法
[[ expression ]] 用法
== 左侧字符串是否和右侧的PATTERN相同
注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
注意: 此表达式用于[[ ]]中;扩展的正则表达式
- 示例:判断文件后缀
#使用通配符
FILENAME=file.log
[[ "$FILENAME" == *.log ]]
echo $?
#使用正则匹配
FILENAME=file.log
[[ "$FILENAME" =~ .*\.log ]]
echo $?
- 示例:判断合法的非负整数
N=100
[[ "$N" =~ ^[0-9]+$ ]]
echo $?
- 判断合法的ip地址
#!/bin/bash
#
#******************************************************************
#Author: yoob
#QQ: 2291887277
#Date: 2023-12-22
#FileName: check_ip.sh
#URL: http://www.yoob.com
#Description: The test script
#Copyright (C) 2023 All rights reserved
#*****************************************************************
IP=$1
[[ $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])$ ]] && echo $IP is valid || echo $IP is invalid
文件测试
存在性测试
-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权限
文件属性测试
-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; }
示例:保留当前环境不被破坏
(cd /tmp; umask 666; touch my.key)
组合测试条件
第一种方式
[ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为
真
[ ! EXPRESSION ] 取反
#用例:判断系统版本
[ $ID = "centos" -a $VERSION_ID = "20.40.20" ]; echo $?
[ $ID = "centos" -o $ID = "ubuntu" ]; echo $?
#增强条件判断
[[ $ID =~ "centos|ubuntu|kali" ]]; echo $?
第二种方式
- 结论:如果&& 和 || 混合使用,&& 要在前,|| 放在后
COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND #非,取反
#常用组合用例
NAME=yoob; id $NAME &> /etc/null && echo "id is exists" || echo "id is not exists"
#创建用户
USER_NAME=test001; [ -n id $USER_NAME ]; echo $?
#ping测地址可达性
ping -c1 -W1 $IP &> /etc/null && echo "$IP is up" || { echo "$IP is unreachable";exit; }
#磁盘空间判断
WARNING=10
SPACE_USED=`df -h |sed -nr "/^\/dev\//s/.* ([0-9]{1,3})%.*/\1/p" |sort -nr |head -n1`
[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $WARNING%,will be full" | mail -s diskwarning root || echo "disk is enough"
使用read接受输入
注意:接受标准输入,|会创建爱你
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d '字符' 输入结束符
-t N TIMEOUT为N秒
- 判断用户输入是否为yes
read -p "please input your answer: " answer
answer=`echo $answer |tr "A-Z" "a-z"`
[ $answer = 'y' -o $answer = 'yes' ] && echo "your choose is yes"
[ $answer = 'n' -o $answer = 'no' ] && echo "your choose is no"
- 鸡兔同笼算法
read -p "please input the head number : " head
read -p "please input the foot number : " foot
rabbit=$[$foot/2-$head]
chook=$[$head-$rabbit]
echo "the rabbit is $rabbit"
echo "the chook is $chook"
- 实现运维工作菜单
#!/bin/bash
#
#******************************************************************
#Author: yoob
#QQ: 2291887277
#Date: 2023-12-23
#FileName: work_menu.sh
#URL: http://www.yoob.com
#Description: The test script
#Copyright (C) 2023 All rights reserved
#*****************************************************************
. /etc/init.d/functions
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 ] && echo "备份数据库"
[ $MENU -eq 2 ] && action "清理日志"
[ $MENU -eq 3 ] && action "软件升级"
[ $MENU -eq 4 ] && action "软件回滚"
[ $MENU -eq 5 ] && action "删库跑路"
- 重置网络IP
#!/bin/bash
#
#******************************************************************
#Author: yoob
#QQ: 2291887277
#Date: 2023-12-23
#FileName: reset_ens33.sh
#URL: http://www.yoob.com
#Description: The test script
#Copyright (C) 2023 All rights reserved
#*****************************************************************
read -p "please input your new ipaddr: " NEW_IPADDR
read -p "please input your new getway: " NEW_GATEWAY
read -p "please input your new netmask: " NEW_NETMASK
sed -i "/^IPADDR=/c IPADDR=$NEW_IPADDR" /etc/sysconfig/network-scripts/ifcfg-ens33
sed -i "/^GATEWAY=/c GATEWAY=$NEW_GATEWAY" /etc/sysconfig/network-scripts/ifcfg-ens33
sed -i "/^NETMASK=/c NETMASK=$NEW_NETMASK" /etc/sysconfig/network-scripts/ifcfg-ens33
CHECK_IPADDR=`sed -nr "s/(IPADDR=)(.*)/\2/p" /etc/sysconfig/network-scripts/ifcfg-ens33`
CHECK_GATEWAY=`sed -nr "s/(GATEWAY=)(.*)/\2/p" /etc/sysconfig/network-scripts/ifcfg-ens33`
CHECK_NETMASK=`sed -nr "s/(NETMASK=)(.*)/\2/p" /etc/sysconfig/network-scripts/ifcfg-ens33`
[ $CHECK_IPADDR = $NEW_IPADDR -a $CHECK_GATEWAY = $NEW_GATEWAY -a $CHECK_NETMASK = $NEW_NETMASK ] && { echo "reset ens33 succeed"; ip link set ens33 up; systemctl restart network.service; } || { echo "reset ens33 failed";exit; }
bash shell的配置文件
生效范围
- 全局配置:针对所有用户皆有效
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
- 个人配置:只针对特定用户有效
~/.bash_profile
~/.bashrc
shell登录两种方式分类
- 交互式登录
#放在每个文件最前
/etc/profile
/etc/profile.d/*. sh
/etc/bashrc
~/ .bash_ profile
~/ .bashrc
/etc/bashrc
#放在每个文件最后
/etc/profile.d/*.sh
/etc/bashrc
/etc/profile
/etc/bashrc #此文件执行两次
~/.bashrc
~/.bash_profile
- 直接通过终端输入账号密码登录
- 使用 su - UserName 切换的用户
- 非交互式登录
/etc/profile.d/*.sh
/etc/bashrc
~/.bashrc
- su UserName
- 图形界面下打开的终端
- 执行脚本
- 任何其它的bash实例
按功能划分分类
- Profile类功用: (1) 用于定义环境变量 (2) 运行命令或脚本
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
- Bashrc类功用: (1) 定义命令别名和函数 (2) 定义本地变量
全局:/etc/bashrc
个人:~/.bashrc
编辑配置文件生效
修改profile和bashrc文件后需生效两种方法:
- 重新启动shell进程
- source|. 配置文件 注意:source 会在当前shell中执行脚本,所有一般只用于执行置文件,或在脚本中调用另一个脚本的场景
. ~/.bashrc
Bash 退出任务
保存在~/.bash_logout文件中(用户),在退出登录shell时运行
功能:
- 创建自动备份
- 清除临时文件
流程控制
条件选择
单分支
if 判断条件;then
条件为真的分支代码
fi
双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支
if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fi
条件判断
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case支持glob风格的通配符:
* 任意长度任意字符
? 任意单个字符
[] 指定范围内的任意单
循环
格式1
for NAME [in WORDS ... ] ; do COMMANDS; done
#方式1
for 变量名 in 列表;do
循环体
done
#方式2
for 变量名 in 列表
do
循环体
done
for循环列表的生成方式
{start..end}
$(seq [start [step]] end)
格式2
双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash Shell实现C语言风格 的变量操作
I=10;((I++))
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
循环体
done
函数function
待补充...
其他脚本相关语言
待补充...
数组array
待补充...
字符串处理
待补充...
高级变量
待补充...
Tip
请,本文为笔者整理的学习笔记,仅供个人参考和梳理思路,错漏之处请多多指导。
如,本文参考各种资源整理未,因此未申请原创声明,如有侵权请联系删除。
若,如果需要转载请各位大佬标明出处,园子不大多多捧场。
另,本文仅做学习使用,请勿用于非法途径。