shell不是面向对象语言
变量
shell中赋值的变量值全部为字符串,不存在数字类型
变量分类
全局变量 ≈ 环境变量
局部变量 ≈ 本地变量
赋值方法
变量名建议大写,等号两边不能有空格形式如下
变量名=变量值
VAR=10
取变量值
推荐使用
${变量名}
获取变量值。
如果变量没有赋值,那么$变量名
是一个空符串,容易引起语法错误,而${变量名}
不会引起语法错误。
$变量名
取变量的值
${变量名}
取变量的值
$((变量名))
对变量执行算数运算
$[变量名]
对变量执行算数运算
$(命令)
或者 `命令` 取命令执行结果
导出变量
export
删除变量
unset
查看本地变量
set
查看全局变量
env
判别符
整数判别符
只能作用于整数
-
-eq
或=
或==
等于(equal) -
-ne
或!=
不等于 (not equal) -
-gt
或>
大于(great than) -
-lt
或<
小于(less than) -
-ge
或>=
大于等于(great equal) -
-le
或<=
小于等于(less equal)
$ VAR=10
$ test $VAR -eq 10
$ echo $?
0
文件类型判别符
-
-d
目录文件 -
-f
普通文件 ( Linux中第一个属性为 [-] ) -
-p
管道 -
-l
软连接 -
-c
字符设备 ( 键盘,鼠标 ) -
-b
块设备( 硬盘 ) -
-s
socket
字符串判别符
只能作用于字符串
-
[ -z string ]
string长度为零则真 -
[ -n string ]
string长度不为零则真 -
[ string1 = string2 ]
两个字符串相等为真 -
[ string1 != string2 ]
两个字符串不相等为真
bash-3.2$ VAR=tom
bash-3.2$ [ $VAR = tom ]
bash-3.2$ echo $?
0
条件判断
test 测试条件
-
[ 测试条件 ]
或[[ 测试条件 ]]
两种写法分别对应bash与zsh语法,建议统一使用[[ 测试条件 ]]
满足兼容 -
echo $?
用来查看上一条语句执行结果:0 表示正常结束,非 0 表示出现错误
逻辑运算符
尽量使用短路特性
-
[ !EXPR ]
逻辑非 -
[ EXPR1 -a EXPR2 ]
逻辑与 ( and ) -
[ EXPR1 -o EXPR2 ]
逻辑或 ( or )
bash-3.2$ VAR=10; VALUE=11
bash-3.2$ [ $VAR = 10 -a $VALUE = 11 ]
bash-3.2$ echo $?
0
条件分支
-
if
/then
/elif
/else
/fi
/ **
* then 相当于 "{"
* fi 相当于"}"
*/
#! /bin/bash
echo "Hello young man? Please answer boy or girl."
read BOY_OR_GIRL
if [ "$BOY_OR_GIRL" = boy ]; then
echo 'Hello cowboy!'
elif [ "$BOY_OR_GIRL" = girl ]; then
echo "Hello snow queen!"
else
echo "Sorry, $BOY_OR_GIRL not recognized. Enter yes or no."
fi
-
case
/esac
Shell脚本的case可以匹配字符串和wildcard,每个匹配分支可以有若干条命令,末尾必须以 ;; 结束相当于break。esac相当于case语句结束符。
#! /bin/bash
echo "What's kind of beverage do you like: \n coca \n sprite \n tea"
read BEVERAGE
case "$BEVERAGE" in
[cC][oO][cC][aA])
echo "Here is your cocoa!";;
[sS][pP][rR][iI][tT][eE])
echo "Here is your sprite!";;
[tT][eE][aA])
echo "Here is your tea!";;
*)
echo "Sorry, $BEVERAGE is not available"
esac
循环
-
for
/do
/done
do 相当于 "{", done 相当于 "}"
#! /bin/bash
// 显示当前路径中所有文件信息
for file in `ls`; do
if [ -f "$file" ]; then
ls -l $file
fi
done
-
while
/do
/done
#! /bin/bash
// 三次内输入正确密码
echo "Enter password:"
read PASWD
COUNT=1
while [ "$PASWD" != "secret" -a $COUNT -lt 3 ]; do
echo "Sorry, try again"
read PASWD
COUNT=$(($COUNT+1))
done
位置参数
-
$0
脚本文件名,相当于 argv[0] 。当我们执行 bash a/b.sh 时,$0 的值是 a/b.sh -
$1
、$2
、…… 用来表示参数,$1 表示第一个参数,以此类推 -
$#
入参个数 argc - 1 ( 不包含 argv[0] ) -
$@
$*
入参列表 [$0, $1...] -
$?
上一条命令的Exit status -
$$
获取当前进程号 -
shift
左移命令行参数
管道
-
|
把一个命令的输出传递给另一个命令做输入。 - tee 把结果输出到标准输出的同时另一个副本输出到相应文件。
文件重定向
[1] 0 标准输入 1 标准输出 2 标准出错
-
cmd > file
把标准输出重定向到file中 -
cmd >> file
追加的方法把标准输出重定向到file中 -
cmd > file 2>&1
把标准输出重定向到file中,同时将标准出错也重定向到file中[1] -
cmd < file > file2
输入输出都重定向到file2中 -
cmd < &fd
把文件描述符 fd 作为标准输入 -
cmd > &fd
把文件描述符 fd 作为标准输出 -
cmd < &-
关闭标准输入
函数
函数没有返回值也没有参数列表
#! /bin/bash
foo() {
for name in $@; do
ls -l "$name"
done
}
echo "-->start<--"
foo $@
echo "-->end<--"
函数传参
# 函数声明
foo () {
# 函数体
}
# 函数调用以及传参
foo arg1 arg2 ...
#! /bin/bash
# 判断入参是否是文件
is_directory() {
DIR_NAME=$1
if [ ! -d "$DIR_NAME" ]; then
return 1
else
return 0
fi
}
# 批量创建目录
for DIR in $@; do
if is_directory "$DIR"
# : 表示真
then :
else
echo "$DIR not exist. Creating it now!"
# 创建文件并将标准输出输出到”无底洞“,同时将标准错误输出到标准输出
mkdir "$DIR" > /dev/null 2>&1
# 判断 mkdir 命令执行结果,如果成功则输出提示语句
if [ $? -ne 0 ]; then
echo "Can not create directory $DIR!"
exit 1
fi
fi
done
Shell脚本调试
-
-n
读一遍脚本中的命令但不执行,用于检测脚本中语法错误。 -
-v
一边执行脚本,一边将执行过的脚本命令打印到标准错误输出。 -
-x
将执行过的每一条命令和结果依次打印出来。( 使用频率高 )
使用方式
- 在命令行提供参数
sh -x ./myshell.sh
- shebang中指定,相当于全局设置全局调试
#! /bin/bash -x
- 在脚本中用
set
命令启动或禁用,方便局部设置局部调试
#! /bin/bash
if [ -z "$1" ]; then
# 启动
set -x
echo "ERROR: Insufficient Args"
exit 1
# 取消
set +x
fi
网友评论