基础
文件
后缀名
一般是 .sh ,但任何后缀名都可以,expect 的后缀一般是 exp,不影响脚本的执行。
第一行
#!
例如
#!/bin/bash 使用 bash 执行
#!/bin/expect 使用 expect 执行
运行方式
作为可执行程序
chmod +x ./test.sh
chmod 755 ./test.sh
./test.sh
注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
作为解释器参数
/bin/sh test.sh
/bin/php test.php
/bin/expect test.exp
注释
单行
# 注释
多行
:<<EOF注释注释EOF:<<!注释注释!
用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果。{注释nameechco}
变量
定义赋值
- 变量名与=直接不能有空格
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线 _
- 不能是关键字
常量赋值:
name=”abc”
ages=1
yourName=”abc”
your_name=”abc”
语句赋值
for file in ls /etc
for file in $(ls /etc)
**=** 两侧有空格是会当做命令执行
name=lsecho $name# lsname= lsecho $name# a.php b.phpname = ls# name:command not found
使用
$var_name
${var_name} 定义变量边界
例如:
name=111
echo $name 111
echo $name222 空
echo ${name}222 111222
只读变量
readonly name
删除变量
unset name
变量类型
运行shell时,会同时存在三种变量:
- 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
特殊变量
| 变量 | 含义 |
|---|---|
| $0 | 当前脚本的文件名 |
| $n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
| $# | 传递给脚本或函数的参数个数。 |
| $* | 传递给脚本或函数的所有参数。 |
| $@ | 传递给脚本或函数的所有参数。被双引号(“ “)包含时,与 $* 稍有不同,下面将会讲到。 |
| $? | 上个命令的退出状态,或函数的返回值。 |
| $$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
|
数据类型
string
语法可以是单引号、双引号、或不带引号
name=li lei
name=’li lei’
name=”li lei”
双引号
- 里面可以解析变量
- 里面可以出现转义字符
单引号的限制
- 任何字符原样输出,单引号字符串的变量将不被解析
- 单引号字符串中不能出现单独一个单引号。
拼接
str=”hello $name”
str=”hello ${name}’s cat”
str=”hello “$name”‘s’ cat”
str=’hello ‘$name”‘s cat”
字符的长度
截取
查看 命令替换 的文档
查找
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string=”runoob is a great site”
echo expr index "$string" io # 4
正则提取
# 过滤出11位手机号 -E 正则 -o 只输出匹配结果phone=$(echo $str | grep -Eo '/d{11}')
执行命令
str='ls -al'${str}
alias 需要使用 eval 执行
原因:查看子文章《 shell中命令的执行流程》
shopt -s expand_aliasesalias ll="pwd"str="ll"# ${str} ll: command not found# `$str` ll: command not foundeval $str/var/wwww
数组
定义
list=(v1 v2 v3)
单行定义,逗号分隔
list2=(
v1
v2
v3
)
多行定义 一个一行
list3[0]=v1
list3[1]=v2
list3[100]=v3
单独定义数组的分量,不使用连续的下标,下标范围不限
直接在 for 语句中定义
for v in v1 v2 v3
do
done
读取
格式:${数组[下标]} 单个元素
name=${list[1]}
格式:${数组[@]} | ${数组[*]} 表示所有元素
元素个数
${#array[@]} 或 ${#name[*]}
${#array[1]} //第二个元素的长度
循环
arr=(a,b,c)for s in ${arr[@]}doecho $sdonefor a in a b cdoecho $adone
stirng to array
str=a,b,c# , 替换为空格,形成 a b c 数组接头arr=(${str//,/ })for s in ${arr[@]}doecho $sdone
或者
#!/bin/bashstring="hello,shell,split,test"#对IFS变量 进行替换处理OLD_IFS="$IFS"IFS=","array=($string)IFS="$OLD_IFS"for var in ${array[@]}doecho $vardone
命令替换
命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
diy: 定义了优先执行权
格式:$(<command>) 或 <command>
示例:
echo today is $(date "+%Y-%m-%d")
echo today is `date "+%Y-%m-%d"`
区别:
| $() | `` | |
|---|---|---|
| 直观度 | 比较直观 | 容易混乱 |
| 所有系统类unix | 部分支持 | 都支持 |
| 多层嵌套(可以混合使用) | 支持 | 不支持 |
变量替换
格式: ${<变量>}
https://www.cnblogs.com/itxdm/p/something_of_shellscirpt.html
定义代码边界
firstName=li
fullName=${firstName}lei
fullName=$firstNamelei
取路径各个部分(删除部分)
可以提取出路径、文件名、后缀
# 路径
${file%/*} #(最后一个 / 之前(左)的部分)
# 文件名
${file##*/} #(最后一个 / 以后(右)的部分)
# 后缀名
${file##*.} #(最后一个 . 以后(右)的部分)
file=/var/www/project/old.index.php
符号是去掉左边(在键盘上 # 在 $ 之左边)
echo ${file#/}
var/www/project/old.index.php
echo ${file##/}
old.index.php
echo ${file#.}
index.php
echo ${file##.}
php
% 符号是去掉右边(在键盘上 % 在 $ 之右边)
echo ${file%/}
/var/www/project
echo ${file%%/}
(空)
echo ${file%.}
/var/www/project/old.index
echo ${file%%.}
/var/www/project/old
单一符号是最小匹配;两个符号是最大匹配 *是用来匹配不要的字符,也就是想要去掉的那部分 还有指定字符分隔号,与*配合,决定取哪部分
变量状态赋值
| 变量未定义过或 unset 过 | 变量已赋值空 name=|name=”” : |
变量已赋值非空 name=val |
|||
|---|---|---|---|---|---|
| - | 未定义过则返回 default | echo ${name-default} echo $name |
default 空 |
空 空 |
val val |
| :- | 或为空 | echo ${name:-default} echo $name |
default 空 |
default 空 |
val val |
| + | 不为实则返回 default | echo ${name+default} echo $name |
空 空 |
default 空 |
default val |
| :+ | 不为空 | echo ${name:+default} echo $name |
空 空 |
空 空 |
default val |
| = | 为空返回 default,并将值设置为 default | echo ${name=default} echo $name |
default default |
空 空 |
val val |
| := | echo ${name:=default} echo $name |
default default |
default default |
val val |
|
取子串
${file:<开始点>:<长度>}
${file:<开始点>}
echo ${file:3} // 从index 为3的字符(包含)截取到默认
echo ${file:3:3} // 从index 为3的字符(包含)截取后面3个字符
替换字符串
${file/<搜索>/<替换>}
${file//<搜索>/<替换>}
${file/dir/path} / 代表单个替换
${file//dir/path} // 代表全部替换
删除字符串
${变量#关键字} 若变量内容从头开始的数据符合“关键字”,则将符合的最短数据删除
${变量##关键字} 若变量内容从头开始的数据符合“关键字”,则将符合的最长数据删除
${变量%关键字} 若变量内容从尾开始的数据符合“关键字”,则将符合的最短数据删除
${变量%%关键字} 若变量内容从尾开始的数据符合“关键字”,则将符合的最长数据删除
取长度
${#file}
$(())
整数运算
+-*/%
echo $((2+3))
a=4;b=3
echo $((a*b))
echo $(($a+$b))
进制转换
将其他进制的数转换为10进制
格式: $((<进制>#<值>))
echo $((2#110)) #6
echo $((16#2a)) #42
(())
递增递减变量
a=5;b=7
((a++))
echo a #6
((a—))
echo a #5
((aecho $? #0
((a>b))
echo $? #1
运算符
| 运算符 | 说明 | 举例 |
|---|---|---|
| + | 加法 | expr $a + $b 结果为 30。 |
| - | 减法 | expr $a - $b 结果为 10。 |
| * | 乘法 | expr $a \\* $b 结果为 200。 |
| / | 除法 | expr $b / $a 结果为 2。 |
| % | 取余 | expr $b % $a 结果为 0。 |
| = | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
| == | 相等。用于比较两个数字,相同则返回 true。 | [ $a == $b ] 返回 false。 |
| != | 不相等。用于比较两个数字,不相同则返回 true。 | [ $a != $b ] 返回 true。 |
|
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
| 运算符 | 说明 | 举例 |
|---|---|---|
| -eq | 检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 true。 |
| -ne | 检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
| -gt | 检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。 |
| -lt | 检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。 |
| -ge | 检测左边的数是否大等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。 |
| -le | 检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。 |
|
| 运算符 | 说明 | 举例 |
|---|---|---|
| ! | 非运算,表达式为 true 则返回 false,否则返回 true。 | [ ! false ] 返回 true。 |
| -o | 或运算,有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
| -a | 与运算,两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
|
| 运算符 | 说明 | 举例 |
|---|---|---|
| = | 检测两个字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
| != | 检测两个字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
| -z | 检测字符串长度是否为0,为0返回 true。 | [ -z $a ] 返回 false。 |
| -n | 检测字符串长度是否为0,不为0返回 true。 | [ -z $a ] 返回 true。 |
| str | 检测字符串是否为空,不为空返回 true。 | [ $a ] 返回 true。 |
|
| 操作符 | 说明 | 举例 |
|---|---|---|
| -b file | 检测文件是否是块设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
| -c file | 检测文件是否是字符设备文件,如果是,则返回 true。 | [ -b $file ] 返回 false。 |
| -d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false。 |
| -f file | 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 | [ -f $file ] 返回 true。 |
| -g file | 检测文件是否设置了 SGID 位,如果是,则返回 true。 | [ -g $file ] 返回 false。 |
| -k file | 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 | [ -k $file ] 返回 false。 |
| -p file | 检测文件是否是具名管道,如果是,则返回 true。 | [ -p $file ] 返回 false。 |
| -u file | 检测文件是否设置了 SUID 位,如果是,则返回 true。 | [ -u $file ] 返回 false。 |
| -r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true。 |
| -w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true。 |
| -x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true。 |
| -s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
| -e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true。 |
|
输出
echo
下面的转义字符都可以用在 echo 中:
| 转义字符 | 含义 |
|---|---|
| \\ | 反斜杠 |
| \a | 警报,响铃 |
| \b | 退格(删除键) |
| \f | 换页(FF),将当前位置移到下页开头 |
| \n | 换行 |
| \r | 回车 |
| \t | 水平制表符(tab键) |
| \v | 垂直制表符 |
echo -e 可以转义上面的字符
echo -E 不转义,也是默认值
echo -n 当前命令结束后不换行
printf
命令的语法:printf format-string [arguments…]
format-string 为格式控制字符串,arguments 为参数列表。
列表
定义
格式1:空格分隔
list = a1 a2 a3
格式2:逗号分隔
list = {a1,a2,a3}
# 方式1
names = dog am
# 方式2
语句
条件语句
if [ 表达式 ]
then
#语句1
elif test 表达式
then
#语句2
else
#语句3
fi
或
if [ 表达式 ]; then 语句; else 语句; fi;
表达式
https://www.cnblogs.com/kaishirenshi/p/9729800.html
分支语句
case 值 in
模式1)
语句;
;;
模式2)
语句;
;;
*)
语句;
;;
esac
循环语句
for
for 值 in 列表
do
执行语句
done
列表生成方式
for i in {1 2 3 4 5 6 7 8 9 10}
for i in {1..10}
for i in $(seq 1 10)
DIR="/var"
for k in $(ls $DIR)
while
while [ 表达式 ]
do
执行语句
done
until
与while相同,只是当表达式返回false 的时候继续运行
循环控制
break n
跳出当前循环
continue
跳出本次循环
函数
https://blog.csdn.net/linyonfeng/article/details/81249762
定义函数
fuc1 () {
执行语句
}
function func2 () {
执行语句
[return 结果] //外部也可以通过$? 来获取结果
}
函数的参数
前9个通过 $n 来获取
大于9个的参数通过 ${n} 来获取
变量的生效范围
local命令是用来定义一个局部变量的,它只能定义在函数中,并且随着函数的结束而被销毁
function foo()
{
#全局变量赋值
a=1
#本地变量赋值
local b=2
}
#调用函数
foo
echo $a
#1
echo $b
#空
返回值
默认 返回值为最后一条命令的执行结果
手动指定返回码return 0~255
其他值返回方式:
https://blog.csdn.net/weixin_33788244/article/details/92021783
函数为子程序调用+标准输出
function add()
{
res=$1+$2
echo $res
}
val=$(add 1000 2000)
echo $val
#3000
使用引用返回
function myfunc()
{
local __resultvar=$1
local myresult='some value'
eval $__resultvar="'$myresult'"
}
myfunc result
echo $result
使用全局变量
删除函数
当只有func_name方法时
unset func_name 可以将方法删除
当func_name方法 和fanc_name变量同时存在是
unset -f func_name 才可以将方法删除
也是就是说:usnet 语句会先删除变量,当变量不能存在时会移除同名的方法
引入其他文件
. filename
或
source filename
重定向
输入重定向 覆盖
>> 输出重定向 追加
< 输入重定向
