目录
概念:
shell脚本的本质:
shell脚本编程:
shell变量:
变量的定义格式:
变量的分类
自定义变量:
环境变量:
命令变量与命令行参数:
预定义变量:
shell中的语句
功能性语句
read(类似c当中 scanf)
expr
let
test
字符串测试
整数测试
文件属性测试
结构性语句
if...then...fi
基本结构
分层结构
嵌套结构
elif(多路分支结构)
case语句
for循环
for语句的几种书写格式
while循环
循环控制语句
数组
定义数组
获取数组
数组切片
gcc编译步骤
概念:
shell脚本的本质:
shell命令的有序集合
shell既是应用程序又是脚本语言,并且是解释型语言,不需要编译,解释一条执行一条。
shell脚本编程:
将shell命令结合一些按照一定逻辑集合到一起,写一个 .sh文件,实现一个或多个功能,这个脚本不用编译直接执行
创建shell脚本文件的步骤:
1. 创建一个脚本文件
touch xxx.sh
2. 将脚本文件的权限修改为可执行
chmod 777 xxx.sh
3. 编辑脚本内容
vi xxx.sh
4. 执行脚本文件
./xxx.sh 或 bash xxx.sh
练习:
1)在当前路径下创建file_1到file_5, 5个普通文件
2)删除 file_2和file_3文件(使用通配符)
3)将剩下的file文件用tar压缩成bz2的格式
4)将压缩文件复制到家目录下
5)进入到家目录解压压缩文件
6)删除压缩包
touch file_{1..5}
rm file_[23]
tar -cvjf file.tar.bz2 file_[^23]
cp file.tar.bz2 ~
cd ~
tar -xvf file.tar.bz2
rm file.tar.bz2
shell变量:
shell中允许建立变量存储数据,但是不支持数据类型
(如:整型、字符、浮点类型),所有赋值给变量的值都解释为一串字符
变量的定义格式:
变量名=值
注:等号两边不能有空格
取shell变量的值:$变量名
变量的分类
自定义变量:
YY=hello # YY="hello world"
echo $YY
XX=$YY ---> 将 YY 的值赋值给 XX
echo $XX
unset 变量名 ---> 取消该变量的值
环境变量:
系统配置好的、内置变量
使用命令查看系统环境变量: printenv或 env
export 变量名=值 临时终端有效
永久生效只需要将这个命令放到用户目录下 .bashrc 文件中,当前用户永久有效。
若放到 /etc/bash.bashrc 这个文件中所有用户永久有效
命令变量与命令行参数:
$0 执行的脚本名
$1-$9、${10}-${n} 命令行空格传的参数 n:第几个命令行参数
$# 命令行参数个数除 $0
$@$* 遍历输出命令行参数内容
预定义变量:
$? 获取的是上一个命令是否是正确的执行结果
0:真 非0:假
$$ 获取当前shell的进程 PID
shell中的语句
1) 说明性语句
以 #开始到该行结束,不被解释执行
#!/bin/bash告诉操作系统使用哪种类型的shell执行此脚本文件
2) 功能性语句
任意的shell命令、用户程序或其他的shell程序
3) 结构性语句
条件测试语句、多路分支语句、循环语句、循环控制语句
功能性语句
read(类似c当中 scanf)
从终端获取值赋值给变量
格式:read 变量名1 变量名2...
加提示语句:read-p"提示字符串"变量名1 变量名2 ...
注:把终端读入空格隔开的第一个单词赋值给第一个变量,第二个单词赋值给第二个变量,依次类推赋值,剩余所有单词赋值给最后一个变量。
expr
算术运算命令expr 主要用于进行简单的整数运算,包括(+)、减(-)、乘(*)、整除(/)、求模(%)等操作
注意:
1) 运算符左右两侧必须有空格
2) *和()必须加转义字符,\*、\( \)
3) expr语句可以直接输出运算结果
如:expr \( 12 + 3 \) \* 2
NUM=`expr \( 12 + 3 \) \* 2`:将运算结果赋值给变量
read -p "要输入的值" val1 val2 val3
expr \( $val1 + $val2 \) \* $val3
let
在运算中不能有空格
运算结果需要赋值给一个变量
变量参与运算的过程不用加 $ 取值
test
test 语句可以测试三种对象
字符串 整数 文件属性
字符串测试
s1 = s2 测试两个字符串的内容是否一样
test "hello" = "world"
echo $? # 1 相等为真,不相等为假
s1 != s2 测试字符串的内容是否有差异
test "hello" != "hello"
echo $? # 1 相等为假,不相等为真
-z s1 测试s1字符串长度是否为0
test -z ""
echo $? # 0 字符串长度为0
test -z "hello"
echo $? # 1 字符串长度不为0
-n s1 测试s1字符串长度是否不为空 (空的时候为1,反之为0)
test -n ""
echo $? # 1 字符串长度为空,则为假
test -n "hello"
echo $? # 0 字符串有长度为真
整数测试
a -eq b 测试a和b是否相等的 # equal
read A B
test $A -eq $B
echo $? # 如果两个数相等则为真,反之为假
a -ne b 测试 a 和 b是否不相等 # no equal
read A B
test $A -ne $B
echo $? # 如果两个数不相等则为真,反之为假
a -gt b 测试 a 是否大于 b # greater than
read A B
test $A -gt $B
echo $? # 如果a大于b则为真,反之为假
a -ge b 测试 a 是否大于等于 b # greater equal than
read A B
test $A -ge $B
echo $? # 如果a大于等b则为真,反之为假
a -lt b 测试 a 是否小于 b # less than
read A B
test $A -lt $B
echo $? # 如果a小于b则为真,反之为假
a -le b 测试 a 是否小于等于 b # less eqaul than
read A B
test $A -le $B
echo $? # 如果a小于等于b则为真,反之为假
文件属性测试
-d name 测试name是否为一个目录
test -d 路径
echo $? # 如果name是目录则为真,反之为假
-f name 测试name是否为一个普通文件
test -f 路径
echo $? # 如果name是普通文件则为真,反之为假
-e name 测试文件是否存在
test -e 路径
echo $? # 如果文件或目录存在则为真,反之为假
结构性语句
if...then...fi
基本结构
if 表达式
then
命令表
fi
分层结构
if 表达式
then
命令表1
else
命令表2
fi
嵌套结构
if 表达式1
then
if 表达式2
then
命令表 2
else
命令表3
fi
else
命令表
fi
elif(多路分支结构)
if 表达式1
then
命令表1
elif 表达式2
then
命令表2
elif 表达式3
then
命令表3
...
else
表达式 n
fi
注意:
如果表达式为真, 则执行命令表中的命令; 否则退出if语句, 即执行fi后面的语句。
if和fi是条件语句的语句括号, 必须成对使用;
命令表中的命令可以是一条, 也可以是若干条。
补充操作符:
! 非运算 例如 [ ! false ] 返回 true
&& 逻辑与 例如 [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑或 例如 [[ $a -lt 100 || $b -gt 100 ]] 返回 true
case语句
格式:
case 变量 in
模式1)
命令表1
;;
模式2)
命令表2
;;
*)
命令表n
;;
esac
工作方式:
取值后面必须为关键字 in ,每一个模式必须以右括号结束。
取值可以为变量或者常量,取值检测匹配的每一个模式
一旦模式匹配,其间所有命令开始执行直至 ;;
执行完匹配模式相应的命令不会再继续匹配其他的模式
如果无一匹配模式,使用 * 号捕获该值
| 或者 ; 转换模式
学生成绩管理系统,用shell中的case实现
90-100:A
80-89:B
70-79:C
60-69:D
<60:不及格
for循环
格式:
for 变量名 in 单词表
do
命令表
done
执行顺序:
变量依次取单词表中的各个单词, 每取一次单词, 就执行一次循环体中的命令. 循环次数由单词表中的单词数确定. 命令表中的命令可以是一条, 也可以是由分号或换行符分开的多条
for I in 1 2 3 4 5 6 7 8 9 10
do
echo "$I"
done
for语句的几种书写格式
变量I从单词表中取值
1) for I in 1 2 3 4 5 6 7 8 9 10 do ... done
变量I从 1-10个数中取值
2) for I in {1..10} do ... done
变量I从命令行取值,省略in、单词表
3) for I do ... done
./脚本名 1 2 3 4 5
书写格式类似C语言
4) for (( i = 0; i < 10; i++ )) do ... done
for (( i = 0; i < 10; i++ ))
do
echo "$i"
done
while循环
格式:
while 命令或表达式
do
命令表
done
执行顺序:
while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。
I=1
while [ $I -lt 10 ]
do
echo $I
(( I++ ))
done
echo $(( I++ ))
循环控制语句
breakn:结束n层循环
continuen:跳过n层本次循环,继续下一个循环
for (( i = 0; i < 10; i++ ))
do
for (( j = 0; j < 10; j++ ))
do
if [ $j -eq 3 ]
then
# continue
# continue 2
# break
break 2
fi
echo "$i:$j"
done
done
数组
定义数组
在shell当中,用小括号 ( ) 来表示数组,数组元素之间用空格来隔开
1. 数组名=(value1 value2 value3 ...)
2. 数组名=(
value1
value2
...
)
3. 通过键值对的形式赋值
数组名=([0]=value1 [1]=value2)
4. 通过分别定义数组变量的方式来定义
数组名[0]="value1"
数组名[1]="value2"
5. 列表名="value0value1 value2"
数组名=($列表名)
注意:
1. 数组中的元素,必须以空格来隔开
2. 定义数组以其索引,可以不按顺序来定义的 如:数组名=([0]=value0 [1]=value2 [8]=array)
3. 字符串是数组中最重要的数据类型,可以通过 ($str) 转成数组
获取数组
1. 获取单个数组元素
${数组名[下标]}
2. 获取数组全部内容
${数组名[@]}或 ${数组名[*]}
3. 获取数组元素的个数
${#数组名[@]} 或 ${#数组名[*]}
数组切片
取数组中的某一段的元素的值
格式:
${数组名[@或*]:起始位置:长度}
gcc编译步骤
预处理:处理以#开头的内容,展开头文件、替换宏定义、删除注释,但是不会进行语法检查。
gcc -E xxx.c -o xxx.i
编译:进行语法检查,将.i文件转化成.s汇编文件
gcc -S xxx.i -o xxx.s
汇编:将汇编文件转化成二进制文件(不可执行)
gcc -c xxx.s -o xxx.o
链接:链接库文件,将不可执行的二进制文件转化成可执行的二进制
gcc xxx.o -o xxx
写 Makefile 时一般这样写
gcc xxx.o -o xxx
gcc -c xxx.c -o xxx.o