目录
一、变量
1. 普通变量
2. 环境变量
3. 位置变量
4. 特殊变量
二、输入输出
1. read命令接收输入
2. echo命令输出字符串
三、表达式
1. 算术表达式
2. 逻辑表达式
四、分支控制
1. if 分支
2. case 分支
五、循环控制
1. for 循环
2. while 循环
3. until 循环
4. select 循环
六、函数
1. 函数的格式
2. 函数的返回值
3. 函数参数
4. 库函数
shell脚本只有一种数据类型,就是string字符串类型。
变量名必须是字母开头,可以包含数字、下划线等,不能有空格,不能使用关键字。
变量取值,可以与其他字符串构成新的字符串
变量赋值,用“=”赋值两端无空格
环境变量的级别:
查看系统的环境变量:
echo:显示某个环境变量,如 echo $PATH
export:设置一个新环境变量,export PATH=&PATH:/...要添加的路径.../
env:显示所有环境变量
unset:清除环境变量
set:显示本地定义的shell变量和环境变量
查看环境变量
#include
int main(int argc, char* argv[], char* env[]) {
for (int i = 0; env[i]; ++i) {
printf("env[%d]: %s\n", i, env[i]);
}
}
通过环境变量区分root用户和普通用户
#include
#include
#include
int main() {
char* who = getenv("USER");
if (strcmp(who, "root") == 0) {
printf("user: %s\n", who);
}
else {
printf("user: %s, 权限不够\n", who);
}
}
自定义环境变量
#include
#include
#include
#define MY_ENV "myenv"
int main() {
char* myenv = getenv(MY_ENV);
if (myenv == NULL) {
printf("%s, not found\n", MY_ENV);
}
else {
printf("%s = %s\n", MY_ENV, myenv);
}
return 0;
}
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
echo $4
echo $5
echo $6
echo $7
echo $8
echo $9
打印命令行指令参数选项
命令行指令通过不同的参数执行不同的任务
#include
#include
#include
#include
int main(int argc, char* argv[], char* env[]) {
if (argc != 2) {
printf("usage: \n\t%s [-a/-b/-c/-ab/-ac/-bc/-abc]\n", argv[0]);
return 1;
}
if (strcmp("-a", argv[1]) == 0) {
printf("功能%s\n", argv[1]);
}
else if (strcmp("-b", argv[1]) == 0) {
printf("功能%s\n", argv[1]);
}
else if (strcmp("-ab", argv[1]) == 0) {
printf("功能%s\n", argv[1]);
}
else if (strcmp("-abc", argv[1]) == 0) {
printf("功能%s\n", argv[1]);
}
//...
}
#!/bin/bash
echo $#
echo $*
echo命令加上 -n 选项,输出不换号
echo命令加上 -e 选项,支持转义字符
echo的引用与转义
expr命令:+ - * / % (乘法运算符必须加上"",其他运算符可加可不加)
let命令:可赋值和计算
算术扩展格式:双小括号
bc工具:yum install -y bc
通过 test命令 进行逻辑判断:
复合条件判断:
test命令可用 [ ] 中括号等价替换,注意 "[ " 和 " ]",前后中括号之间都要有空格
文件或目录属性判断:
if 分支的结构
# 格式1:if 条件; then 执行; fi
#! /bin/bash
a=5
if [ $a -gt 3 ]
then
echo "OK"
fi
# 格式2:if 条件1; then 执行1; else 执行2; fi
#! /bin/bash
a=1
if [ $a -gt 3 ]; then
echo "OK"
else
echo "error"
fi
# 格式3:if 条件1; then 执行1; elif 条件2; then 执行2; else 执行3; fi
#! /bin/bash
a=5
if [ $a -gt 8 ]; then
echo ">8"
elif [ $a -gt 3 ]; then
echo ">3"
else
echo "<3"
fi
case 变量值 in
模式 1)
命令序列1;;
模式 2)
命令序列2;;
.......
*)
默认命令序列;;
esac
case值得注意的特点
#!/bin/bash
read read -p "请输入一个字符,并按Enter键确定:" KEY
case "$KEY" in
[a-z]|[A-Z]) echo "您输入的是字母!";;
[0-9]) echo "您输入的是数字!";;
*) echo "您输入的是空格,功能键或其他控制字符。";;
esac
for val in valuelist...
do
commands
done
for((exp1;exp2;exp3))
do
commands
done
# exp1 初始化
# exp2 变量取值范围
# exp3 变量增量
while command
do
command
...
done
# while后面的命令执行成功则循环,否则跳出循环
while 简单循环
通过while脚本实现给文件内容加行号
until command
do
commands
done
# until后面的命令成功的时候结束循环,失败的时候进入循环
通过until脚本监控某用户是否登录
#!/bin/bash
until who | grep "$1" >/dev/null 2>&1
do
sleep 3
done
echo "Be careaful, $1 is online now!"
# 2>&1 是把标准错误输出重定向
# /dev/null 是系统垃圾堆,将所有接收到的数据都丢失
# 若该用户未登录则命令指令不成功,即循环等待
# 当用户登录,until突出循环
select var in menu...
do
commands
done
# select 后面跟的是菜单
# in 关键字后面是菜单取值列表
# 这些值以空格隔开
# 用户选择数字对应菜单值
# 变量var获取值后执行循环一次
#!/bin/bash
PS3="Please Select[1-4]:"
select m in new insert modify delete exit;
do
if [ $m = exit ]; then
break
fi
echo $m;
done
# PS3是一个环境变量,它是selet的提示符
#shell中的函数定义
#其中function为关键字,FUNCTION_NAME为函数名
function FUNCTION_NAME(){
command1 #函数体中可以有多个语句,不允许有空语句
command2
...
}
#省略关键字function,效果一致
FUNCTION_NAME(){
command1
command2
...
}
# 函数名后的小括号中没有参数
# 函数function关键字可以不写
# 函数必须遵循先定义再定义原则
#!/bin/bash
echo -n "请输入文件名:"
read FILE
function checkFileExist(){
if [ -f $FILE ]; then
return 0
else
return 1
fi
}
echo "call function checkFileExist"
checkFileExist
if [ $? -eq 0 ]; then
echo "$FILE exist"
else
echo "$FILE not exist"
fi
#!/bin/bash
function checkFileExist(){
if [ -f $1 ]; then
return 0
else
return 1
fi
}
echo "Call function countLine"
checkFileExist $1 # 函数调用
if [ $? -eq 0 ]; then
echo "$1 exist"
else
echo "$1 not exist"
fi
#执行脚本时,通过直接向脚本传递文件全路径的方式传递参数
#可以看到这种方式不会因为测试文件的不一样而修改脚本本身的内容,非常简单
由于Shell是一门面向过程的脚本型语言,而且用户主要是Linux系统管理人员,所以并没有非常活跃的社区,这也造成了Shell缺乏第三方函数库,所以在很多时候需要系统管理人员根据实际工作的需要自行开发函数库。下面建立一个叫 funclib 的函数库,该函数库目前只有一个函数,用于判断文件是否存在。
_checkFileExists(){
if [ -f $1 ]; then
echo "File:$1 exists"
else
echo "File:$1 not exist"
fi
}
其他脚本在希望直接调用_checkFileExists函数时,可以通过直接加载 funclib 函数库的方式实现。加载方式有如下两种:
#使用“点”命令
$ . /PATH/TO/LIB
#使用source命令
$ source /PATH/TO/LIB
假设现在有个脚本想要直接调用_checkFileExists函数,可以通过加载 funclib 函数库来实现。
可以通过 set 和 unset 命令查看当期那内存中已经定义和载入的函数,使用 unset 清除函数,函数修改后必须重新载入。