目录

前言

周二

Linux命令拓展

1 软件安装相关的命令

1.1 离线安装命令--dpkg

1.2 在线安装命令--apt-get

2. 归档和拆包的命令(tar)(重点)

3. 文件操作相关的命令

3.1 cat(重点)-----> 回显文件内容到终端

3.2 head ----> 从文件头开始回显

3.3 tail ----> 从文件的末尾开始回显

3.4 重定向符(重点) ---->  ‘ > 和 >> ’

3.5 find(重点) ----> 查到文件的命令

3.6 file(重点) ---> 查看文件属性的信息

3.7 grep(重点) ----> 从文件中搜索字符串

3.8 | (重点) -----> 管道符(用来连接多个命令)

3.9 echo ----> 打印的命令

3.10 read ----> 读数据到变量中

3.11 cut ---> 字符串剪切的命令

4.通配符的使用

5.文件属性操作相关的命令

5.1 修改文件权限的命令 --- chmod

5.2 修改用户所属的组 ---> chgrp

5.3 修改用户所属的用户和组 ----> chown

6、链接文件的创建

6.1 创建软链接文件

6.2 创建硬链接文件

7、开关机和重启的命令

周三

shell编程(上)

1. 一些小知识

1.1编程语言的分类

1.2 shell语言使用的解析器

1.3 什么是shell

1.4 shell脚本文件

2. 程序执行

3. shell中的变量

3.1 变量的定义

3.2 变量的引用

3.3 shell中的位置变量

3.4 定义变量使用的关键字

4. shell中的数组

4.1 数组的定义

4.2 数组的访问

4.3 数组的拼接

周四

shell编程(中)

1. 输入输出命令

1.1 输入命令 ---> read

1.2 输出的命令 ---> echo

2. shell中的算术运算

2.1 shell中算数运算的介绍

2.2 使用 (()) 完成算数运算

2.3 使用 $[] 完成算数运算

2.4 使用 expr 命令完成算数运算

3. if...else分支语句

3.1 if...else分支语句的语法格式

3.2 if...else测试代码

4. test命令学习

4.1 test命令的介绍

4.2 字符串对象比较

4.3 整数对象比较

4.4 ⽂件类型判断

4.5 ⽂件权限判断

4.6 ⽂件⽐较

4.7 逻辑运算

5. case...in分支语句

5.1 case...in分支语句的格式

5.2 case...in的参考案例

6. while循环语句

6.1 while循环语句的语法格式

6.2 while循环的参考代码

周五

shell编程(下)及makefile编程

1、for循环

1.1 for循环的语法格式

1.2 参考案例

2、select ... in语句

2.1 select in的语法格式

2.2 select...in的测试代码

3、break和continue关键字

3.1 break使用

3.2 continue

3.3 测试代码

4、shell中的函数

4.1 shell中函数的定义

4.2 函数的调用

4.3 在函数体内获取函数的实参值

4.4 函数的返回值

4.5 参考案例

5. Makefile

5.1 Makefile概括

5.2 Makefile的基本语法构成

5.3 规则构成

5.4 Makefile中的变量

5.5 Makefile中的函数

反思与总结


前言

不知不觉已经是在这学习的第四个周末了,这周因为中秋假期的原因,周一没上课,这四天的课主要讲了Linux命令的拓展、shell编程和Makefile编程:其中linux命令主要是讲了网络配置、软件安装,围绕linux的文件讲了一些常用的指令;对于shell编程,和C语言类似,讲了变量、数组、算数运算、分支结构、循环结构和函数;对于最后的Makefile编程,讲了规则构成、变量的使用、Makefile内置的函数和简单的Makefile文件的编写。

这周有点浑浑噩噩,一方面假期结束没调整好状态,另一方面从C语言转到其他方面的学习,有很多需要理解的地方,尤其是刚开始没太跟上老师的思路和节奏,所以这次回顾总结会全盘把老师讲的东西过一遍。

同样,写此文章,是想以这种碎碎念的方式回顾重点、重复盲点、加深印象,复习、总结和反思本周的学习,仅供后期自己回顾使用。知识体系不完善,内容也不详细,仅供笔者复习使用。如果是有需要笔记,或者对这方面感兴趣,可以私信我,发你完整的知识体系和详细内容的笔记。如有任何错误请多指正,也欢迎友好交流,定会虚心听取大佬的宝贵意见

周二

Linux命令拓展

1 软件安装相关的命令

1.1 离线安装命令--dpkg

1. linux安装软件包的后缀ubuntu  ----> .debredhat  ----> .rpm2. 离线软件包命名的方式sl_           3.03-17build2   _amd64   .deb|                   |            |       |软件的名称        版本号         架构    软件包的后缀amd64 ----> x64架构的软件包,64位系统i386  ----> x86架构的软件包,32位系统3. 安装软件的命令(重点)sudo dpkg -i  软件安装包的名字4. 卸载软件的命令(重点)sudo dpkg -r  软件的名字5. 查看软件安装的列表信息sudo dpkg -l  软件的名字6. 查看软件的安装路径sudo dpkg -L  软件的名字7. 完全卸载软件 sudo dpkg -P  软件的名字

1.2 在线安装命令--apt-get

在线安装软件需要配置ubuntu系统的源,在线安装软件时从哪个服务器中下载安装软件。

因此需要给ubuntu系统指定源,国内常用的软件源有:清华源, 阿里源,163源。

清华源的网址:https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/
1、在线安装   sudo apt-get install  软件名eg:sudo apt-get install oneko //安装追⿏标的⼩猫sudo apt-get install frozen-bubble //安装泡泡⻰sudo apt-get install cmatrix //代码⾬sudo apt-get install bastet //俄罗斯⽅块运行软件,oneko  ----> 在前台运行oneko &  ----> 进程在后台运行2、下载软件包sudo apt-get download 软件名eg:sudo apt-get download oneko3、卸载软件sudo apt-get remove 软件名sudo apt-get autoremove  软件名  ----> 卸载的更加干净eg:sudo apt-get remove oneko4、下载软件的源码sudo apt-get source 软件名eg:linux@ubuntu:~$ sudo apt-get source oneko出现以下错误:Reading package lists... DoneE: You must put some 'deb-src' URIs in your sources.list解决办法:修改/etc/apt/sources.list文件将deb-src的网址取消注释,其他全部注释。需要重新执行sudo apt-get update更新源,再次执行下载的命令。注:测试完成之后,将/etc/apt/sources.list修改为默认的状态。再将deb-src的网址注释掉

2. 归档和拆包的命令(tar)(重点

1. 参数-c : 归档-x : 拆包-f : 指定归档和拆包的文件的名字,必须放到所有参数的最后边-v : 显示归档和拆包的过程的详细信息-j : 使用bzip2的压缩格式进行压缩-J : 使用xz的压缩格式进行压缩-z : 使用gzip的压缩格式进行压缩2. 归档的命令-->单纯的进行归档并没有压缩tar -cvf 归档之后的文件名.tar   要归档的文件名/文件夹3. 拆包的命令tar -xvf 要拆包的文件名.tar4. 归档的同时进行压缩tar -jvcf  归档之后的文件名.tar.bz2  要归档的文件名/文件夹tar -jxvf 要拆包的文件名.tar.bz2 tar -Jvcf  归档之后的文件名.tar.xz  要归档的文件名/文件夹tar -Jxvf 要拆包的文件名.tar.xztar -zvcf  归档之后的文件名.tar.gz  要归档的文件名/文件夹tar -zxvf 要拆包的文件名.tar.gz5. 万能的拆包并解压缩的命令tar -vxf 要拆包的文件名.tar.xxxx 表示bz2,gz, xz

3. 文件操作相关的命令

3.1 cat(重点)-----> 回显文件内容到终端

用法:   cat  文件名  ----> 回显文件内容到终端cat  -n 文件名  ----> 回显文件内容到终端, 显示行号cat 文件名1  文件名2 > 文件名3  ---> 将文件名1和文件名2中的内容重定向到文件名3中(实现多个文件的拼接)> : 重定向
案例
linux@ubuntu:day01$ cat hello.c
#include <stdio.h>linux@ubuntu:day01$ cat world.c
int main(int argc, const char *argv[])
{return 0;
}linux@ubuntu:day01$ cat hello.c world.c
#include <stdio.h>int main(int argc, const char *argv[])
{return 0;
}linux@ubuntu:day01$ cat hello.c world.c > helloworld.c
linux@ubuntu:day01$ cat helloworld.c
#include <stdio.h>int main(int argc, const char *argv[])
{return 0;
}

3.2 head ----> 从文件头开始回显

用法:head 文件名  ----> 默认回显文件的前10行,如果不够就全部回显head -5 文件名   -----> 显示前五行

3.3 tail ----> 从文件的末尾开始回显

用法:tail 文件名  ----> 默认回显文件末尾的后10行,如果不够就全部回显tail -5 文件名   -----> 显示文件末尾的后五行

3.4 重定向符(重点) ---->  ‘ > 和 >> ’

重定向:将命令的执行的结果重定向到其他文件中,不在终端回显。shell命令 > 文件 : 将命令的结果重定向到“文件”中,如果文件不存在则创建文件,如果文件存在,并且文件中有内容,则先将内容清空在进行重定向。shell命令 >> 文件 : 将命令的结果重定向到“文件”中,如果文件不存在则创建文件,如果文件存在,并且文件中有内容,从文件中的内容末尾开始追加内容。

3.5 find(重点) ----> 查到文件的命令

用法:find  路径  -name  要查找的文件名    ----> 从“路径”下查找“要查找的文件名”注:文件名中可以使用通配符 *(多个字符)  ?(单个字符)
eg:find . -name  hello.c   ---> 在当前目录查找hello.cfind /etc  -name passwd  ----> 在/etc目录下查找passwd文件

3.6 file(重点) ---> 查看文件属性的信息

用法:file 文件名
eg:
linux@ubuntu:day02$ gcc hello.c -o hello
linux@ubuntu:day02$ file hellohello: ELF   ----> 可执行文件的格式64-bit LSB shared object,  ----> 64位可执行程序 小端对齐x86-64, ----> 可执行程序的架构version 1 (SYSV), dynamically linked,  ----> 动态链接interpreter /lib64/ld-linux-x86-64.so.2,   ---> 动态库BuildID[sha1]=aecfe163e5e53998d09c4ec5becb342c6d672a73, for GNU/Linux 3.2.0, not stripped  ----> 没有压缩

3.7 grep(重点) ----> 从文件中搜索字符串

用法:grep  -参数   "要搜索的字符串"   文件名/目录
参数:-n ----> 显示搜索内容的行号-R ----> 递归搜索,如果是一个目录,必须添加-R参数-i ----> 查找时不区分大小写-w ----> 按照单词进行查找
eg:grep -n  "main"   ./helloworld.c   ---> 从helloworld.c文件中查找main字符串grep -nR "main"   ./          ---> 从当前目录下所有的文件中递归查找main字符串grep -n "linux" /etc/passwd ---> 从文件中查找"linux"字符串grep -n "^linux" /etc/passwd ---> 从文件中查找开头为"linux"字符串grep -n "bash$"  /etc/passwd ---> 从文件中查找结尾为"bash"字符串grep -n "^bash$"  /etc/passwd ---> 从文件中查找开头为"bash"字符串,结尾也为"bash"字符串grep -ni  "MAIN"   ./helloworld.c  ---> 从helloworld.c文件中查找MAIN字符串,不区分大小写grep -nw  "hello"   ./helloworld.c  ---> 从helloworld.c文件中查找hello字符串,按照单词查找

3.8 | (重点) -----> 管道符(用来连接多个命令)

用法:shell命令1 | shell命令2 | shell命令3 | ......
功能:将前一个命令的结果作为后一个命令的输入
eg :查找当前目录下的hello.c文件:ls | grep "hello.c"  ----> 从当前目录下查找是否存在hello.c文件练习题1> passwd文件中内容的解析(/etc/passwd)linux : x : 1000 : 1000:linux,,,:/home/linux:/bin/bash|     |     |      |     |         |          | 用户名  密码  用户ID 组ID   描述信息   家目录     使用bash解析终端的命令2> 使用管道符的方式提取linux用户所在的行的信息grep "^linux" /etc/passwd  -ncat /etc/passwd | grep "^linux"cat -n /etc/passwd | grep "linux"head -46 /etc/passwd | tail -1

3.9 echo ----> 打印的命令

用法:echo "字符串"echo 字符串echo '字符串'  ----> 回显字符串到终端echo ${shell变量的名字}echo $shell变量的名字   ----> 回显变量的值到终端
linux@ubuntu:day01$ echo hello world
hello world
linux@ubuntu:day01$ echo "hello world"
hello world
linux@ubuntu:day01$ echo 'hello world'    ----> 输出字符串
hello world
linux@ubuntu:day01$ name=zhoukai    ----> 定义变量,等号两边不允许有空格,变量的值是一个字符串,可以加'', 可以加"", 可以什么都不加
linux@ubuntu:day01$ echo $name
zhoukai
linux@ubuntu:day01$ echo ${name}    ----> 输出变量的值
zhoukai

3.10 read ----> 读数据到变量中

用法:read shell变量名   ---> 将终端输入的输入读到变量中read -p "提示字符串"  变量名 ---> 先打印一个提示符,将提示符后边输入的内容读到变量中
eg: linux@ubuntu:day01$ read namezhoukai2linux@ubuntu:day01$ echo $namezhoukai2linux@ubuntu:day01$ read -p "please input your name > " nameplease input your name > zhoukai3linux@ubuntu:day01$ echo $namezhoukai3linux@ubuntu:day01$ read -p "please input your name, age > " name ageplease input your name, age > zhoukai 18linux@ubuntu:day01$ echo $namezhoukailinux@ubuntu:day01$ echo $age18linux@ubuntu:day01$ echo $name $agezhoukai 18

3.11 cut ---> 字符串剪切的命令

用法:cut -d "分隔符" -f 截取的域  要截取的文件名及路径案例:grep "^linux" /etc/passwd > ./passwdlinux@ubuntu:day02$ cat passwd linux:x:1000:1000:linux,,,:/home/linux:/bin/bash域  1   2   3    4     5         6           7linux@ubuntu:day02$ cut -d ":" -f 6 ./passwd   ---> 截取第6部分/home/linuxlinux@ubuntu:day02$ cut -d ":" -f 1,6 ./passwd ---> 截取第1,6部分linux:/home/linuxlinux@ubuntu:day02$ cut -d ":" -f 3-4,6 ./passwd  ---> 截取第3to4,6部分1000:1000:/home/linuxlinux@ubuntu:day02$ cut -d ":" -f 3-6 ./passwd    ---> 截取第3to6部分1000:1000:linux,,,:/home/linux案例题:将/etc/passwd文件中linux用户的对应家目录字符串截取出来(grep | cut)grep "^linux" -n /etc/passwd | cut -d ":" -f 7 |                          |     | ---> 第七部分|                             ||                          |---> 冒号分隔||46:linux:x:1000:1000:linux,,,:/home/linux:/bin/bash域 1   2   3   4    5      6         7          8----------------------------------------------------------------grep "^linux" /etc/passwd | cut -d ":" -f 6 |                       |     | ---> 第6部分|                          ||                       |---> 冒号分隔||linux:x:1000:1000:linux,,,:/home/linux:/bin/bash域 1    2   3   4       5         6         7       ----------------------------------------------------------- head -46 /etc/passwd | tail -1 | cut -d ":" -f 6案例题:将/etc/passwd文件中linux用户的用户ID和组ID字符串截取出来(grep | cut)grep "^linux" -n /etc/passwd | cut -d ":" -f 4-5 grep "^linux" /etc/passwd | cut -d ":" -f 3,4

4.通配符的使用

touch  a1.c a2.c a3.c a4.c aa.c ab.c ac.c ad.c aaa.c abb.c acc.c add.c 1. * ----> 匹配多个字符linux@ubuntu:day02$ ls a*.ca1.c  a2.c  a3.c  a4.c  aaa.c  aa.c  abb.c  ab.c  ac.c  acc.c  ad.c  add.c2. ? ----> 匹配单个字符linux@ubuntu:day02$ ls a?.ca1.c  a2.c  a3.c  a4.c  aa.c  ab.c  ac.c  ad.clinux@ubuntu:day02$ ls a??.caaa.c  abb.c  acc.c  add.c3. []  ----> 匹配中括号中的某一个字符linux@ubuntu:day02$ ls a[abcd].c   ---> 第二个字符为abcd的任意一个aa.c  ab.c  ac.c  ad.clinux@ubuntu:day02$ ls a[a-d].c    ---> 第二个字符为a到d的之间的任意一个aa.c  ab.c  ac.c  ad.clinux@ubuntu:day02$ ls a[1-4].c    ---> 第二个字符为1到4的之间的任意一个a1.c  a2.c  a3.c  a4.clinux@ubuntu:day02$ ls a[^1-4].c   ---> 第二个字符除了为1到4之间的任意一个aa.c  ab.c  ac.c  ad.clinux@ubuntu:day02$ ls a[^abcd].c  ---> 第二个字符除了为a到b之间的任意一个a1.c  a2.c  a3.c  a4.c

5.文件属性操作相关的命令

5.1 修改文件权限的命令 --- chmod

-rwxrwxr-x 1 linux linux     16704        Sep 12 23:04       a.out
| |  |  |  |    |    |          |->文件大小     |--> 日期       |---> 文件名
| |  |  |  |    |    |----> 所属的组
| |  |  |  |    |----> 所属的用户
| |  |  |  |-----> 硬链接个数
| |  |  |----> 其他用户的权限
| |  |-----> 文件所属组的权限
| |-----> 文件所属用户的权限
|-------> 文件的类型1. 文件类型bsp-lcd :块设备文件/套接字文件/管道文件/普通文件/链接文件/字符设备文件/目录2. 文件的权限r ---> 可读(4)w ---> 可写(2)x ---> 可执行(1)3. 所有的用户a ---> 所有的用户(all)u ---> 普通的用户(user)g ---> 组(group)o ---> 其他用户(other)4. 权限操作+ ---> 添加权限- ---> 移除权限= ---> 修改权限augo + +-= + rwx : 从中各选取一个或多个任意组合5. 修改文件的权限 ----> chmod方式1:chmod u+x  hello.c    ---> 给hello.c所属用户添加可执行的权限chmod g-w  hello.c    ---> 给hello.c所属组删除写的权限chmod o=rw hello.c    ---> 给hello.c所属其他用户修改为可读可写的权限chmod a+rwx hello.c   ---> 给hello.c所有的人都添加可读可写可执行的权限方式2:chmod 0777 hello.c   ---> ||||----> 设置其他用户的权限:可读+可写+可执行(4+2+1)|||----> 设置所属组的权限:可读+可写+可执行(4+2+1)||----> 设置所属用户的权限:可读+可写+可执行(4+2+1)|----> 表示8进制数,0可以省略具体设置文件为哪种权限,根据需要将:可读(4)+可写(2)+可执行(1),进行任意组合,让后将对应的权限的数据进行加法运算即可。

二进制到十六进制之间的转算(4位二进制对应1位16进制,记住8421)

0b * * * *

​    8 4 2 1

二进制到八进制之间的转算(3位二进制对应1位16进制,记住421)

5.2 修改用户所属的组 ---> chgrp

chgrp root hello.c  ----> 修改hello.c文件所属的组为root用户

5.3 修改用户所属的用户和组 ----> chown

chown root:root  hello.c   ---> 修改hello.c文件所属的用户和组
chown root:  hello.c   ---> 修改hello.c文件所属的用户和组
chown :root  hello.c   ---> 修改hello.c文件所属的组
chown root  hello.c    ---> 修改hello.c文件所属的用户

6、链接文件的创建

在查看文件的详细信息时有一个硬链接数:
-rw-rw-r-- 1 root root 101 Aug 10 18:17 hello.c如果是一个文件,则硬链接数表示此文件的硬链接文件的个数;
如果是一个目录,则硬链接数表示此目录下的子目录的个数。

6.1 创建软链接文件

用法:ln -s 绝对路径/被链接的文件或者目录  绝对路径/链接的文件或目录的名字总结:1> 创建软链接文件时既可以对普通文件创建软连接文件,也可以对目录创建软链接文件;    2> 在创建软连接文件时使用绝对路径,尽量不要使用相对路径;原因:如果使用相对路径时,当将软连接文件拷贝到其他目录下时,软连接文件和被链接的文件的链接关系将失效;如果使用绝对路径链接关系就不会失效。3> windows系统是不支持软链接文件,因此在后续的课程中,在解压缩***.tar.xx压缩文件时,要求在ubuntu中使用tar命令解压缩。4> 软链接文件的属性为----> l5> 创建软链接文件之后,硬链接数不会增加。6> 如果删除被链接的文件,则对应的软链接文件会失效,如果重新创建对应的文件,软链接文件会重新生效。
练习题:// 对目录创建软链接文件ln -s /home/linux/DC22081/day01 /home/linux/DC22081/day01-s// 对文件创建软链接文件ln -s /home/linux/DC22081/day01/hello.c /home/linux/DC22081/day01/hellos.c将windows的共享文件夹在ubuntu系统的家目录下创建一个软链接文件:ln -s /mnt/hgfs/自己共享文件夹的名字  /home/linux/share创建软链接文件的使用场合:当文件夹的路径特别长的时候,可以对此目录创建软链接文件

6.2 创建硬链接文件

用法:ln  绝对路径/被链接的文件  决定路径/链接的文件名总结:1> 只能对普通文件创建硬链接文件2> 创建硬链接文件之后,硬链接数会增加3> 被硬链接的文件和硬链接文件最终访问的是同一块内存空间。通过ls -i命令查看文件的inode号, 在linux系统中每一个文件都存在一个唯一的inode号。linux@ubuntu:day02$ ln /home/linux/DC22071/day02/hello.c /home/linux/DC22071/day02/hello.cpplinux@ubuntu:day02$ lshello  hello.c  hello.cpp  helloworld.c  passwdlinux@ubuntu:day02$ ls -i1460544 hello    1459921 hello.cpp     1460545 passwd1459921 hello.c  1460535 helloworld.c4> 不管删除硬链接文件还是被硬链接的文件,硬盘中的数据都不会被删除,如果删除被硬链接的文件,创建的硬链接文件依然可以使用。只有将被硬链接的文件所有的硬链接文件和源文件都删除,硬盘中的数据才会被删除。

7、开关机和重启的命令

关机命令:sudo shutdown  17:10    ----> 17:10关机sudo shutdown  +10      ----> 10分钟之后关机sudo shutdown  now      ----> 立即关机重启命令:sudo reboot  17:10    ----> 17:10重启sudo reboot  +10      ----> 10分钟之后重启sudo reboot  now      ----> 立即重启

周三

shell编程(上)

1. 一些小知识

和C语言对比学习,两者在思路上本质上是一样的,区别就是shell是由一行一行的命令组成的,一些逻辑方面要更灵活,思路没问题后,注意shell和C语言在语法上的不同即可。

要注意的是,在shell编程里面,不管是变量、数组、还是函数的内容,都是字符串,在做数值运算的时候要格外注意。

1.1编程语言的分类


编译型语言:需要使用编译器将其编译生成可执行的文件,c  C++ 解释型语言:需要使用解析器区解析语言。shell脚本语言  python

1.2 shell语言使用的解析器

1. bash解析器   ----> ubuntu系统使用的是bash解析器
2. sh解析器     ----> 开发板中启动linux系统时,使用的sh解析器
3. csh
4. ksh

1.3 什么是shell

shell翻译成中文:贝壳
shell是用来对linux系统起到保护的作用,通过输入命令,shell解析器解析输入的命令,
根据命令的功能最终实现硬件的控制,并将结果回显到终端之上。

1.4 shell脚本文件

1. shell脚本文件的名字一般以.sh结尾(不一定是.sh结尾的)
2. 在shell脚本文件中本质上就是很多liunx命令的集合,并不是简单的将命令在shell脚本文件中罗列,会有一定的代码的逻辑。3. 当执行脚本文件时,脚本文件中的命令会按照逻辑依次执行,并完成一个特定的功能。

2. 程序执行

1. 创建一个01first.sh文件2. 打开文件,添加以下内容#!/bin/bash            # 使用的是那个脚本文件的解析器read -p "请输入你的名字 > " nameecho 你好${name}3. 给脚本文件添加可执行的权限chmod 0777 01first.sh4. 执行脚本文件4.1 方式1:给脚本文件添加可执行权限之后,./01first.sh  执行脚本文件脚本文件必须具有可执行的权限,会重新打开一个新的终端执行脚本文件,并将结果返回到当前终端之上。4.2 方式2:bash ./01first.sh脚本文件可以不具有可执行的权限,会重新打开一个新的终端执行脚本文件,并将结果返回到当前终端之上。4.3 方式3:source 01first.sh脚本文件可以不具有可执行的权限,在当前终端下执行脚本文件,并将结果返回到终端之上。

3. shell中的变量

3.1 变量的定义

格式:变量名=变量值变量名='变量值'变量名="变量值"
1. 在shell中定义变量时,变量是没有数据类型之分的,都当初字符串处理str=helloworldnum=12345678       # 字符串2. 在shell中定义变量时,等号两边不允许出现空格str = helloworld   # error 3. 如果变量的值之间没有空格使用以上三种方式都是一样的str=helloworldstr='helloworld'str="helloworld"4. 如果变量的值之间有空格时,使用单引号或者双引号将字符串括起来str=hello world     # errorstr='hello world'str="hello world"5. 如果使用某个变量给另外一个变量赋值时,使用双引号括起来var='world'str='hello ${var}'   # ${var}变量的值不会被展开,${var}被当初字符串处理# str='hello ${var}'str="hello ${var}"   # ${var}变量的值会被展开,# str='hello world'

3.2 变量的引用

格式:$变量名或者${变量名}

注意:

        1. 对于初次使用着来说,建议使用${变量名}的方式引用shell中的变量

2. 引用变量时,如果不适用{},会出现文件的场景

    var1=hellovar2=worldvar3=$var1    # OKvar4="$var1 world"  # OKvar5=$var1world     # ERROR 将var1world当初一个变量名,是一个空值var6=${var1}world   # OK
#!/bin/bash
# your code
echo "1. 在shell中定义变量时,变量是没有数据类型之分的,都当初字符串处理"
var1=helloworld
var2=1234567echo var1=${var1}
echo var2=${var2}echo "2. 在shell中定义变量时,等号两边不允许出现空格"
# var3 = helloworldecho "3. 如果变量的值之间没有空格使用以上三种方式都是一样的"
str=helloworld
str='helloworld'
str="helloworld"echo "4. 如果变量的值之间有空格时,使用单引号或者双引号将字符串括起来"
# str=hello world    # error
echo str=${str}
str='hello world'
echo str=${str}
str="hello world"
echo str=${str}echo "5. 如果使用某个变量给另外一个变量赋值时,使用双引号括起来"
var1=hello
var2=world# var3=$var1 world   # error
var6=hello$var2
var7=$var1world
var7=${var1}world
var4='$var1 world'
var5="$var1 world"

3.3 shell中的位置变量

执行shell脚本文件时,给shell脚本文件传递参数$0   ----> 脚本文件的名字
$1   ----> 执行脚本文件时传递的第1个参数
$2   ----> 执行脚本文件时传递的第2个参数
.............
$9   ----> 执行脚本文件时传递的第9个参数
$10  ----> 执行脚本文件时传递的第1个参数,和字符0拼接
$11  ----> 执行脚本文件时传递的第1个参数,和字符1拼接
${10}  ----> 执行脚本文件时传递的第10个参数
${11}  ----> 执行脚本文件时传递的第11个参数
......${n}  ----> 执行脚本文件时传递的第n个参数$*  ----> 获取脚本文件的所有的参数,不包括脚本文件的名字
$@  ----> 获取脚本文件的所有的参数,不包括脚本文件的名字
$#  ----> 获取脚本文件的参数的个数和,不包含脚本文件的名字
#!/bin/bash
# your code
echo '$0脚本文件的名字'
echo  $0echo '$1脚本文件的第1个参数'
echo $1echo '$2脚本文件的第1个参数'
echo $2echo '$10脚本文件的第1个参数和字符0拼接'
echo $10echo '${10}脚本文件的第10个参数'
echo ${10}echo '$* 脚本文件的所有的参数'
echo $*echo '$@ 脚本文件的所有的参数'
echo $@echo '$# 脚本文件的所有的参数的个数'
echo $#

3.4 定义变量使用的关键字

    readonly  ----> 定义只读类型的变量,定义的同时必须进行初始化unset ---> 取消变量的定义,不可以对只读变量取消定义local ---> 定义局部变量, 在shell中默认所有的变量都是全局变量,即时在shell函数中定义的变量也是全局变量,要想在shell函数中的变量变成局部变量需要使用local修饰。
#!/bin/bash
# your codereadonly  name='zhoukai'
echo "name = $name"# 只读的变量不可以被修改
# name="zhangsan"age=18
echo "age = $age"# 取消变量的定义
unset age
echo "age = $age"# 在shell中如果变量没有定义,你使用了此变量,不会报错,变量是一个空值
echo "sex = $sex"# shell中函数的定义
function  func()
{salary=30000    # 在shell的函数中定义的变量默认也是一个全局变量local heigth=180  # 使用local将shell函数中的变量声明为一个局部的变量echo "heigth = $heigth"
}# shell中函数的调用, 直接写函数的名字即可
funcecho "salary = $salary"echo "heigth = $heigth"  # 在函数的外部不可以使用函数中的局部变量

4. shell中的数组

4.1 数组的定义

1. 在shell中只支持一维数组,没有多维数组

2. 在shell中定义数组
            数组名=(初始值1 初始值2 初始值3 ....)

eg:arr=(aa bb 11 22 ee ff)  # 数组的成员个数是6, 下边从0开始数组名=([0]=初始值1 [1]=初始值2 [2]=初始值3 .....)eg:arr=([0]=aa [1]=bb [2]=11 [3]=22)  # 数组的成员个数是4arr=([0]=aa [1]=bb [5]=11 [8]=22)  # 数组的成员个数是4

4.2 数组的访问

1. 访问数组中单个的成员${数组名[下标]}      # 数组的下标从0开始2. 访问数组中的所有的成员${arr[*]}${arr[@]}3. 统计数组中成员的个数${#arr[*]}${#arr[@]}4. 统计数组中某个成员的字符的个数(统计字符串的长度)${#arr[下标]}

4.3 数组的拼接

arr=(${arr1[*]} ${arr2[*]})arr=(${arr1[@]} ${arr2[@]})

周四

shell编程(中)

1. 输入输出命令

1.1 输入命令 ---> read

 read  var1     ----> 将终端的数据读到var1变量中read  var1 var2  ..... ----> 将终端中的数据读到var1和var2中,以空格或者tab键分割的字符串read  -p "提示符字符串"  var1 ---->先回显提示字符串,在提示符后边的数据读到var1变量中 read -t 秒数 var1  ---> “秒数”之后没有输入数据就结束read -n num(个数) var1  ---> 输入num个字符之后结束read -s var1   ----> 输入的数据在终端不回显,类似于输入密码

1.2 输出的命令 ---> echo

echo 字符串   ----> 输出字符串,字符串之间不允许有空格
echo '字符串'
echo "字符串"  ----> 输出字符串,字符串之间可以有空格echo  $var   ----> 输出变量的值
echo  "$var string"  ---> 展开变量的值
echo  "${var}string"
echo  string$var
echo  "string $var"
echo -n "字符串|$变量名"  ---> 取消换行符的输出

2. shell中的算术运算

2.1 shell中算数运算的介绍

1. 再shell中本身是不擅长进行算数运算,shell更加擅长的是命令的执行或者是文件的处理和判断。
        2. shell要想完成算数运算需要借助一些shell命令完成。
            原因:shell中所有变量的定义都被当成字符串处理
        3. 再shell中可以使用以下方式完成算数运算
              ----> ((表达式))
             
----> $[表达式]
             
---->  expr

2.2 使用 (()) 完成算数运算

1. 格式((表达式1, 表达式2, 表达式3, .....))最后一个表达式的结果作为运算的结果返回2. 获取运算的结果((变量名=表达式))变量名=$((表达式))3. 使用时的注意事项在(())可以是复杂的表达式在(())中如果使用变量,变量可以加$,也可以不加$在(())中的运算符两边可以有空格,也可以没有空格
#!/bin/bash
# your code#
((num = 100 + 200))
echo "num = $num"# (())里边可以有多个表达式,最后一个表达式的结果被返回
sum=$((100+200, 300+400))
echo "sum = $sum"# 如果在(())使用变量时,可以加$,也可以不加$
a=100
b=200
sum=$(( a + b ))
echo "sum = $sum"sum=$(( $a + $b ))
echo "sum = $sum"((sum = a + b))
echo "sum = $sum"# 以下写法中sum不可以加$
((sum = $a + $b))
echo "sum = $sum"

2.3 使用 $[] 完成算数运算

1. 格式$[表达式1, 表达式2, 表达式3, .....]最后一个表达式的结果作为运算的结果返回2. 获取运算的结果变量名=$[表达式]3. 使用时的注意事项在$[]可以是复杂的表达式在$[]中如果使用变量,变量可以加$,也可以不加$在$[]中的运算符两边可以有空格,也可以没有空格在$[]中必须使用一个变量接收其返回值
#!/bin/bash
# your code#
num=$[100 + 200]
echo "num = $num"# $[]里边可以有多个表达式,最后一个表达式的结果被返回
sum=$[100+200, 300+400]
echo "sum = $sum"# 如果在$[]使用变量时,可以加$,也可以不加$
a=100
b=200
sum=$[a + b]
echo "sum = $sum"sum=$[$a + $b]
echo "sum = $sum"# 在$[]中必须使用一个变量接收其返回值
# $[100+200]   # error

2.4 使用 expr 命令完成算数运算

1. expr是一个shell命令,可以使用man查看expr命令的帮助手册。2. 格式expr  表达式3. 获取表达式的结果命令置换符 : ``(反向单引号,~好键上的单引号)   $()命令置换符的使用可以将命令的结果赋值给某个变量eg:file=`ls ./`   ---> 查看当前目录下的所有文件或目录,将这个结果赋值给file变量file=$(ls ./)变量名=`expr 表达式`变量名=$(expr 表达式)4. 使用expr的注意事项1> 在expr的表达式中如果使用其他的变量时,必须添加$2> 在expr的表达式中运算符两边必须添加空格;原因:expr是一个可执行程序,在这个程序中有main函数,当执行expr命令时,给这个命令传递参数,在expr程序中通过argc和argv获取传递的参数。如果省略运算符两边的空格,expr会看出一个参数,最终解析表达式失败,因此在运算符的两个必须添加空格。expr $a + $b   ----> Okexpr $a+$b     ----> error   解析不会报错,当成一个字符串整体输出3> 使用expr命令时不可以进行自增自减的运算expr $a++    ----> errorexpr $a--    ----> errorexpr $a + 1  ----> okexpr $a - 1  ----> ok4> 在expr命令中使用部分运算符时可能需要转移\(   \)   \>   \<  ......具体这个运算符是否需要转义,根据结果进行分析。5> 在表达式中使用其他的变量时,推荐大家将变量的使用加双引号
#!/bin/bash
# your code# 运算符两边必须有空格
expr 100 + 200# 运算符两边没有空格,当成一个字符串整体输出
expr 100+200# 将运算的结果赋值给一个变量
sum=`expr 100 + 200`
sum=$(expr 100 + 200)
echo "sum = $sum"# 如果表达式中使用其他的变量必须加$
a=300
b=400
sum1=`expr $a + $b`
echo "sum1 = $sum1"
# sum2=`expr a + b`   # 报错,没有整形的参数
# echo "sum2 = $sum2"sum3=`expr \( $a + $b \) \* 2`
echo "sum3 = $sum3"
5. expr进行算数运算ARG1 \< ARG2ARG1 \<= ARG2ARG1 = ARG2ARG1 != ARG2ARG1 \>= ARG2ARG1 \> ARG2  成立返回1,不成立返回0,使用变量时,给变量加"",部分运算符需要进行转义ARG1 + ARG2ARG1 - ARG2ARG1 \* ARG2ARG1 / ARG2ARG1 % ARG2使用变量时,给变量加"",部分运算符需要进行转义ARG1 \| ARG2    ---> 变量的值为空或者为0,都表示假如果两个表达式都为真时,则返回ARG1的值如果两个表达式都为假使,则返回0如果两个表达式有一个为真,则返回为真的表达式的值ARG1 \& ARG2只有两个变量的值都为真(变量的值不为0或者非空),则输出ARG1的值,否则输出0
#!/bin/bash
# your coderead -p "请从终端输入两个整数 > " a b ret=`expr $a \> $b`echo "ret = $ret"
#!/bin/bash
# your coderead -p "请从终端输入两个整数,进行|运算 > " a b ret=`expr "$a" \| "$b"`echo "ret = $ret"linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行|运算 > 0 0
ret = 0
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行|运算 > 0 100
ret = 100
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行|运算 > 100 0
ret = 100
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行|运算 > 200 100
ret = 200
#!/bin/bash
# your coderead -p "请从终端输入两个整数,进行&运算 > " a b ret=`expr "$a" \& "$b"`echo "ret = $ret"linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行&运算 > 0 0
ret = 0
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行&运算 > 0 100
ret = 0
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行&运算 > 100 0
ret = 0
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行&运算 > 200 100
ret = 200
linux@ubuntu:~/DC22081/day03$ bash 04expr.sh
请从终端输入两个整数,进行&运算 > 100 200
ret = 100
6. expr进行字符串的处理
expr match STRING REGEXP从STRING字符串中和REGEXP字符串进行比较,如果比较成功返回相同字符的个数,不成功返回0,从第一个字符开始比较expr substr STRING POS LENGTH从STRING字符串中截取子字符串,POS从那个位置开始截取,LENGTH截取字符串的长度;注:STRING字符串的第一个字符的起始编号为1expr index STRING CHARS从STRING字符串中查找第一次出现CHARS字符的位置,成功返回字符的编号,没有找到返回0;如果一个字符串中有多个CHARS,返回第一次出现此字符的位置注:STRING字符串的第一个字符的起始编号为1expr length STRING计算字符串的长度 等价于${#STRING}www.hqyj.com
#!/bin/bash
# your codestr="www.baidu.com"num=`expr match "$str" "www"`
echo "num = $num"   # 3 # 字符串的比较是从第一个字符开始的
num=`expr match "$str" "baidu"`
echo "num = $num"   # 0# 只有整个子字符串中所有的字符匹配成功之后,才会返回匹配的个数
num=`expr match "$str" "wwws"`
echo "num = $num"   # 0# 从字符串中截取子字符串
substr=`expr substr $str 5 5`
echo "substr = $substr"# 查找字符串第一次出现字符的位置
index=`expr index $str '.'`
echo "index = $index"# 计算字符串的长度
length=`expr length $str`
echo "length = $length"echo "length = ${#str}"

3. if...else分支语句

3.1 if...else分支语句的语法格式

1. 第一种写法if 表达式 thenshell命令fi
2. 第二种写法if 表达式 thenshell语句elseshell语句fi
3. 第三种写法if 表达式then shell语句elif 表达式thenshell语句elif 表达式thenshell语句......省略很多elif分支......elseshell语句fi
如果if和then写到一行,中间需要添加一个分号1. 第一种写法if 表达式  ; thenshell命令fi
2. 第二种写法if 表达式 ; thenshell语句elseshell语句fi
3. 第三种写法if 表达式 ; then shell语句elif 表达式 ; thenshell语句elif 表达式 ; thenshell语句......省略很多elif分支......elseshell语句fi

3.2 if...else测试代码

#!/bin/bash
# your coderead -p "请输入你的成绩(score>=0 && score <=100) > " score if ((score < 0 || score > 100))
then echo "输入的成绩不合理,请重新输入"exit
fiif ((score >= 90)) ; then echo "A"
elif ((score >= 80)) ; thenecho "B"
elif ((score >= 70)) ; then echo "C"
elif ((score >= 60)) ; then echo "D"
elseecho "E"
fi

4. test命令学习

4.1 test命令的介绍

test是一个shell命令,可以使用man test查看命令的帮助手册。test命令的功能:可以对数值(整数|字符串)进行比较,也可以用来判断文件的类型。test命令的格式:test  表达式[ 表达式 ]    -----> 最终调用的是test命令注意事项:1> 表达式中出现,变量,运算符,或者参数,前后必须有空格2> 在表达式中使用其他变量时,必须添加$, 使用的变量最后使用""括起来3> 部分运算符需要进行转移, \(   \)4> test命令经常和if语句配合使用,进行文件的判断if [ 表达式 ] ; then   ----> 中括号的前后必须添加空格 shell语句
fiif test 表达式 ; thenshell语句
fi

4.2 字符串对象比较


字符串对象(⼀定要注意在进⾏字符串的判断的时候都需要加上“”,“$a” "hello")-z 判断字符串是否为空 ----> 为空返回真,非空返回假-n 判断字符串是否为⾮空  ---> 非空为真,空为假=或== 都是⽤来判读字符串是否相等   ---> 成立返回真,不成立返回假!= 不等于   ---> 成立返回真,不成立返回假\> ⼤于 (防⽌误认为重定向)   ---> 成立返回真,不成立返回假\< ⼩于     ---> 成立返回真,不成立返回假[ STRING1 = STRING2]
练习题:从终端输入两个字符串进行比较
#!/bin/bash
# your code
read -p "请输入第一个字符串 > " str1
read -p "请输入第二个字符串 > " str2 # 判断两个字符串是否为空,只要有一个为空就退出# 如果在一个中括号中有多个表达式进行逻辑运算,使用-a或者-o
# if [ \( -n "$str1" \) -a \( -n "$str2" \) ] ; then
#     echo "这两个字符串都是非空"
# else
#     echo "这两个字符串至少有一个为空"
#     exit
# fi# if [ \( -z "$str1" \) -o  \( -z "$str2" \) ] ; then
#    echo "这两个字符串至少有一个为空"
#    exit
#else
#   echo "这两个字符串都是非空"
#fi# 如果多个[]表达式直接进行逻辑运算时,使用&&或者||
if [ \( -z "$str1" \) ] ||  [ \( -z "$str2" \) ] ; then echo "这两个字符串至少有一个为空" exit
else echo "这两个字符串都是非空"
fiif [ "$str1" = "$str2" ] ; then echo "$str1 等于 $str2"
elif [ "$str1" \> "$str2" ] ; then echo "$str1 大于 $str2"
elif [ "$str1" \< "$str2" ] ; then echo "$str1 小于 $str2"
fi

4.3 整数对象比较

-eq : 等于
-ne : 不等于
-gt : ⼤于
-lt : ⼩于
-ge : ⼤于等于
-le : ⼩于等于[ INTEGER1 -eq INTEGER2 ]
练习:请输⼊⼀个学⽣的成绩,判断它是A,B,C,D,E
[90-100] A
[80-89] B
[70-79] C
[60-69] D
<60 E#!/bin/bash
# your coderead -p "请输入你的成绩(score>=0 && score <=100) > " score if  [ "$score" -lt 0 -o  "$score" -gt 100 ]
then echo "输入的成绩不合理,请重新输入"exit
fiif [ $score -gt 90 ] ; then echo "A"
elif [ $score -gt 80 ] ; thenecho "B"
elif [ $score -gt 70 ] ; then echo "C"
elif [ $score -gt 60 ] ; then echo "D"
elseecho "E"
fi

4.4 ⽂件类型判断

-b filename 判断⽂件是否存在,是否是块设备
-c filename 判断⽂件是否存在,是否是字符设备
-d filename 判断⽂件是否存在,是否是⽬录
-f filename 判断⽂件是否存在,是否是普通⽂件
-p filename 判断⽂件是否存在,是否是管道⽂件
-L filename 判断⽂件是否存在,是否是链接⽂件 (经测试链接⽂件也是普通⽂件)
-S filename 判断⽂件是否存在,是否是套接字⽂件
-e filename 判断⽂件是否存在
-s filename 判断⽂件是否存在,判断⽂件是否为空[ -b  FILE1 ]
练习:
1.请输⼊⽂件的名字,判断⽂件是否是普通⽂件,还是⽬录#!/bin/bash
# your codeif [ $# -ne 1 ] ; thenecho "输入的参数不合理,请重新输入"echo "usage: $0 文件的名字及路径"exit
else if [ $1 == "help" ] ; then echo "usage: $0 文件的名字及路径"exitelseif [ -f $1 ] ; then echo "$1是一个普通的文件"elif [ -d $1 ] ; then echo "$1是一个目录"elseecho "$1既不是普通的文件,也不是目录"fifi
fi 

4.5 ⽂件权限判断

-r filename 判断⽂件是否存在,是否有可读权限
-w filename 判断⽂件是否存在,是否有可写权限
-x filename 判断⽂件是否存在,是否有可执⾏权限[ -r  FILE1 ]

4.6 ⽂件⽐较

-nt ⽂件是否更新
-ot ⽂件是否更旧
-ef ⽂件的inode是否⼀致[ filename1 -nt filename2 ]

4.7 逻辑运算

-a 与 &&
-o 或 ||
! ⾮ !
 练习:1.请输⼊⽂件的名字,判断⽂件是否是普通⽂件,判断文件是否为脚本文件,如果为脚本文件,判断脚本文件是否具有可执行的权限,如果没有可执行的权限则添加可执行的权限。file命令查看文件的属性,cut命令截取“shell”字符串命令置换符获取命令的结果#!/bin/bash
# your codeif [ $# -ne 1 ] ; then echo "输入的参数不合理,请重新输入"echo "usage: $0 文件的名字及路径"exit
else if [ $1 == "help" ] ; then echo "usage: $0 文件的名字及路径"exitelseif [ -f $1 ] ; then echo "$1 是一个普通文件"fileType=`file $1 | cut -d " " -f 3`if [ "$fileType" == "shell" ] ; then echo "$1 是一个脚本文件"if [ -x $1 ] ; then echo "$1 脚本文件具有可执行的权限"else echo "$1 脚本文件不具有可执行的权限"chmod a+x $1fielse echo "$1 不是一个脚本文件"fielseecho "$1 不是一个普通文件"fifi
fi

5. case...in分支语句

5.1 case...in分支语句的格式

1. 格式:case $变量名 in      -----> 类似于switch case语句常量表达式1)     -----> 类似于 case 常量表达式:shell语句;;          -----> 类似于break, 不可以省略常量表达式2)shell语句;;......常量表达式n)shell语句;;*)             -----> 类似于defaultshell语句;;esac2. 注意事项:1> 在case的分支语句中,两个分号(;;)是不可以省略的, 除了最后一个分支的两个分号可以省略。2> 常量表达式的书写a)    ----> 字符aa|b|c|d)   -----> 表示abcd中的任意一个字符Y|Yes|yes|YES)   ----> 表示字符串中的任意一个[a-zA-Z])  -----> 表示a-zA-Z中的任意一个字符*)   -----> 使用了*通配符[1-9])   -----> 数字1-9直接的任意一个

5.2 case...in的参考案例

输入一个字符,判断是字符,数字,还是标点符号。#!/bin/bash
# your coderead -p "请输入一个字符 > " chcase $ch in [a-zA-Z])echo "$ch 是一个字符";;    #----> 这个两个分号不可以省略[0-9])echo "$ch 是一个数字";;\,|\.|\!|\?|\;)echo "$ch 是一个标点符号";;*)echo "$ch 是一个特殊的字符";;   #----> 最后一个分支的两个分号可以省略esac
从终端输入年和月份,判断月份的天数#!/bin/bash
# your coderead -p "请输入你的年和月" year mouthcase $mouth in 1|3|5|7|8|10|12)echo "$year年 $mouth月共计31天";;4|6|9|11)echo "$year年 $mouth月共计30天";;2)if (( $year % 4 == 0 && $year % 100 != 0 || $year %400 == 0)) ; thenecho "$year年 $mouth月共计29天"elseecho "$year年 $mouth月共计28天"fi;;*)echo "输入的月份不合理";;
esac

6. while循环语句

6.1 while循环语句的语法格式


1. 方式1 while ((表达式))do shell语句done2. 方式2:while和test配合使用while [ 表达式 ]do shell语句done3. 方式3:while [ true ]    ----> 等价于while(1){}死循环doshlle语句done

6.2 while循环的参考代码

#!/bin/bash
# your codesum=0
i=0
while (( i <= 100 ))
do((sum=sum+i))((i++))
done echo "sum = $sum"sum=0
i=0
while [ $i -le 100 ]
do sum=$[sum + i]i=`expr $i + 1`
doneecho "sum = $sum"

周五

shell编程(下)及makefile编程

1、for循环

1.1 for循环的语法格式

1. 格式1 for ((表达式1; 表达式2; 表达式3))do shell语句4done2. 格式2for 变量名 in  单词列表    ====> 类似于python中for循环的写法do shell语句done单词列表:多个单词以空格隔开,组成一个列表执行过程:单词列表中的每个单词依次赋值给“变量名”,每赋值依次执行依次"shell语句",直到所有的单词列表中的单词赋值给变量名之后,就循环结束。

1.2 参考案例

使用for循环变量数组中的所有的成员:
#!/bin/bash
# your codearr=(11 22 33 44 55 66 77 88 99 111)for ((i=0; i < ${#arr[*]}; i++))
doecho "arr[$i] = ${arr[i]}"
donei=0
for value in 11 22 33 44 55 66 77 88 99 111
do  echo "arr[$i] = $value"((i++))
donei=0
for value in ${arr[*]}
do  echo "arr[$i] = $value"((i++))
done
for循环的嵌套,使用for循环打印以下图形
*
**
***
****
*****#!/bin/bash
# your coderead -p "请输入打印的行数 > " linefor ((i = 0; i < line; i++))
do for ((j = 0; j <= i; j++))do echo -n "*"doneecho ""    # 输出换行符
done #  seq命令可以输出连续的数字,或者输出固定间隔的数字,或者输出指定格式的数字
# seq 起始数字 间隔大小 结束数字
# 如果间隔大小不写,默认间隔大小为1for i in  `seq 1 $line`
do for j in `seq 1 $i`do echo -n "*"doneecho ""    # 输出换行符
done
定义一个数组,使用冒泡排序的方式对数组进行排序
arr=(10 70 90 60 30 100 50 94 28 9)#!/bin/bash
# your codearr=(10 70 90 60 30 100 50 94 28 9)echo "arr = ${arr[*]}"for ((i = 0; i < ${#arr[*]}-1; i++))
do for (( j = 0; j < ${#arr[*]}-1-$i; j++))doif ((${arr[j]} > ${arr[j+1]})) ; thentmp=${arr[j+1]}arr[j+1]=${arr[j]}arr[j]=$tmpfidone
doneecho "arr = ${arr[*]}"
#!/bin/bash
# your codearr=(10 70 90 60 30 100 50 94 28 9)echo "arr = ${arr[*]}"x=`expr ${#arr[*]} - 2`for i in `seq 0 $x`
do y=`expr ${#arr[*]} - 2 - $i`for j in `seq 0 $y` doif ((${arr[j]} > ${arr[j+1]})) ; thentmp=${arr[j+1]}arr[j+1]=${arr[j]}arr[j]=$tmpfidone
doneecho "arr = ${arr[*]}"
#!/bin/bash
# your codearr=(10 70 90 60 30 100 50 94 28 9)echo "arr = ${arr[*]}"for i in `seq 0 \`expr ${#arr[*]} - 2\``
do for j in `seq 0 \`expr ${#arr[*]} - 2 - $i\``doif ((${arr[j]} > ${arr[j+1]})) ; thentmp=${arr[j+1]}arr[j+1]=${arr[j]}arr[j]=$tmpfidone
doneecho "arr = ${arr[*]}"

2、select ... in语句

2.1 select in的语法格式

select主要用于菜单的选择,提高代码的交互性;
        执行过程,通过输入编号,选择"单词列表"中的某个单词赋值给"变量名",

格式select 变量名 in 单词列表doshell语句done

2.2 select...in的测试代码

#!/bin/bash
# your codeselect var in one two three fore five
doecho "var = $var"
donelinux@ubuntu:~/DC22081/day04$ bash 04select.sh
1) one
2) two
3) three
4) fore
5) five    ---> 输出一个菜单选项的列表
#? 1    ----> 只能输入菜单列表选项对应的编号
var = one
#? 2
var = two
#? 5
var = five
#? 6   ----> 输入没有的编号则赋一个空值
var =
#?     ----> 什么都不输入,直接回车则菜单选项列表重新输出
1) one
2) two
3) three
4) fore
5) five
#? ^C   ----> ctrl + c强制退出
select in语句经常和case in分支语句配合输入
#!/bin/bash
# your codeselect os in macOS Ubuntu Windows ios Android
docase $os in macOS)echo "当前打开的是$os";;Ubuntu)echo "当前打开的是$os";;Windows)echo "当前打开的是$os";;ios)echo "当前打开的是$os";;Android)echo "当前打开的是$os";;*)echo "操作系统不存在,请重新输入";;esac
done

3、break和continue关键字

3.1 break使用

1. 格式break n   1> n是一个大于等于1的数字,如果n=1可以省略不写2> 作用:退出n层循环体

3.2 continue

1. 格式continue n1> n是一个大于等于1的数字,如果n=1可以省略不写2> 作用:退出n层循环

3.3 测试代码

#!/bin/bash
# your codefor i in `seq 0 9`
do echo -n "$i"if [ $i -gt 5 ] ; then break 1    # 退出1层循环体fiecho -n "*"
done
echo ""for i in `seq 0 9`
do echo -n "$i"if [ $i -gt 5 ] ; then continue 1    # 退出1层循环,执行下一次的循环fiecho -n "*"
done
echo ""linux@ubuntu:~/DC22081/day04$ bash 06break.sh
0*1*2*3*4*5*6
0*1*2*3*4*5*6789
#!/bin/bash
# your codefor i in `seq 0 9`
do echo -n "$i"for j in `seq 0 9`do echo -n "#"if [ $j -gt 5 ] ; then break 2    # 退出2层循环体fiecho -n "$j"doneecho -n "*"echo ""
done
echo ""for i in `seq 0 9`
do echo -n "$i"for j in `seq 0 9`do echo -n "#"if [ $j -gt 5 ] ; then continue 2    # 退出2层循环,进行下一次的循环fiecho -n "$j"doneecho -n "*"echo ""
done
echo ""

4、shell中的函数

4.1 shell中函数的定义

格式:function  函数名(){函数体}注意事项:1> shell中的函数定义需要使用function进行修饰, 但是function也可以省略不写,一般不省略2> shell中的函数也遵循先定义后使用的原则3> shell中的函数不需要写返回类型,函数是否具有返回值要看函数如何书写。4> shell中的函数形参不需要写,及()中不需要写任何内容,函数是否具有形参要看函数如何书写。

4.2 函数的调用

1. 函数没有形参,因此不需要传递实参值
            函数名
    
        2. 函数有形参,需要传递实参值
            函数名 实参列表(多个实参使用空格隔开)

4.3 在函数体内获取函数的实参值

在函数体内获取函数的实参值通过位置变量获取
$0   ----> 在函数中使用$0时依然表示脚本文件的名字,不表示函数的名字
$1
...$n   ----> 第n个参数,如果n大于等于10使用花括号括起来$*   ----> 所有的参数
$@   ----> 所有的参数
$#   ----> 参数的个数之和

4.4 函数的返回值

1. 在shell中,函数中定义的变量默认也是全局变量,因此在函数外可以直接使用函数体内定义的全局变量

2. 使用return进行返回, 使用return返回时,只能返回0-255直接的数,获取通过return返回的返回值,通过$?接收函数的返回值

3. 在函数中使用echo输出函数的返回值,需要使用命令置换符(``)将函数包含起来,获取函数的返回结果

4.5 参考案例

#!/bin/bash
# your code# 1. 定义一个函数,函数没有参数,没有返回值
function print()
{echo "hello world"
}# 2. 定义一个函数,函数具有形参,没有返回值
function show()
{echo '$0'" = $0"echo '$1'" = $1"echo '$2'" = $2"echo '$*'" = $*"echo '$@'" = $@"echo '$#'" = $#"
}# 3. 定义一个函数,函数具有形参,具有返回值,通过全局变量返回
function add_func1()
{sum1=0sum1=$(($1 + $2))
}# 4. 定义一个函数,函数具有形参,具有返回值,通过return返回,只能返回0-255直接的数
function add_func2()
{local sum2=0sum2=$(($1 + $2))return $sum2
}# 5. 定义一个函数,函数具有形参,具有返回值,通过echo返回
function add_func3()
{local sum3=0sum3=$(($1 + $2))echo $sum3
}
# 1. 函数的调用
print# 2. 调用函数
show hello world# 3. 函数的调用
add_func1 1000 2000
echo "add_func1 sum1 = $sum1"# 4. 函数的调用, 使用$?获取函数通过return返回的值
add_func2 50 100
echo "add_func2 sum2 = $?"add_func2 200 100
echo "add_func2 sum2 = $?"# 5. 函数的调用, 使用命令置换符获取函数的返回值
sum3=`add_func3 10000 20000`
echo "add_func3 sum3 = $sum3"
练习题:通过输入用户名,判断用户是否存在,获取用户名对应的uid1> 输⼊⽤户的名字,判断该系统上是否存在该⽤户 (封装为函数get_user_line(),若⽤户存在则返回用户名/etc/passwd中的⾏号)提示:line=`grep "^输入的用户名"  /etc/passwd  -n | cut -d ":" -f 1`2> 若存在该⽤户将这个⽤户名uid显示出来  (封装为函数get_user_info(),将上述的函数返回的⾏号传递到这个函数中,返回uid)提示:uid=`head -46 /etc/passwd | tail -1 | cut -d ":" -f 3`#!/bin/bash
# your coderead -p "请输入用户名 > " userNamefunction get_user_line() {local line=`grep "^$1"  /etc/passwd  -n | cut -d ":" -f 1`return $line
}function get_user_info() {local uid=`head -$1 /etc/passwd | tail -1 | cut -d ":" -f 3`echo $uid
}get_user_line $userName
line=$?
echo $line
if [ $line  -ne 0 ] ; then echo "用户存在"uid=`get_user_info $line`echo $uid
elseecho "用户不存在"
fi

5. Makefile

5.1 Makefile概括

5.1.1 什么是Makefile

Makefile是用于工程项目管理的一个文本文件,文件名为Makefile的文本文件
        Makefile文件首字母可以大写,也可以小写,一般使用大写的Makefile .
        如果Makefile和makefile文件都存在,执行make命令时,默认执行小写的makefile文件

5.1.2 什么是make

make是一个执行Makefile的工具,是一个解释器,当执行make命令时,会解析Makefile文件中的依赖关系,通过依赖关系最终执行编译相关的命令,完成对整个项目代码的编译。
        make可执行程序在/usr/bin目录下(默认ubuntu系统都自带make命令)
         sudo apt-get install make

5.1.3 Makefile的用途

Makefile用来描述整个工程的编译和链接规则,用来执行软件工程的自动化编译

5.1.4 怎么学习Makefile

1. 理论基础
            软件构造过程、程序的编译和链接
            面向依赖的思维(思想)
            编译代码的4个阶段:预处理  ---> 编译  ---> 汇编  ---> 链接
    
            面向依赖的思想:
                得到.elf可执行文件-依赖-> ***.o -依赖-> ***.s -依赖-> ***.i -依赖-> ***.c

2. 项目编程基础
            C语言基础
            C语言项目基础(多文件编程)
            C语言实战之学生成绩管理系统
            多文件源码管理、头文件包含、函数的声明与定义

5.1.5 Makefile的原理

源文件 --> 编译 --> 目标文件 --> 链接 --> 可执行文件
        hello.c -----> hello.o  ----->    hello

Makefile编译源文件分成两步?
1》本质上可以通过一步直接生成可执行文件。通过一步编译完成,最终生成可执行文件:gcc score.c main.c -o stu_manage缺点:只要修改一个.c文件,,其他的.c文件都会被重新编译,浪费时间。2》分成两部目的是。对于大型工程文件,源文件很多,如果修改某个源文件,当你再次执行make的时候,如果源文件没有修改,make是不会重新生成目标文件,只有修改过的源文件才会重新生成目标文件,最后进行链接即可,这样可以有效的节约代码的编译时间。通过两步编译完成,最终生成可执行文件:第一步:(-c:只编译不链接,将.c文件编译生成.o文件)gcc -c score.c -o score.o gcc -c main.c -o main.o第二步:(链接:将所有的.o文件链接生成可执行文件)gcc score.o main.o -o stu_manage优点:如果修改了一个.c文件只需要重新编译修改过的.c文件将其生成.o文件,最后将所有的.o文件重新链接生成可执行文件即可。Makefile文件如何知道源文件是否修改呢?根据文件的时间戳

5.2 Makefile的基本语法构成

5.2.1 Makefile中的基本语法构成
    规则   --》 Makefile的规则
    变量   --》 变量声明
    条件执行  --》 条件执行
    文本、文件名处理函数  --》 函数
    文件包含  --》 可以使用include包含其他的Makefile
    注释  --》 注释
    
5.2.2 规则
    构成Makefile的基本单元、构成依赖关系的核心部件,其它内容可以看作为规则服务

5.2.3 变量
    定义变量,变量没有数据类型,都当成字符串处理,使用:$(VAR)、${VAR}
    可以让Makefile更加灵活

5.2.4 条件执行
    根据某一变量的值来控制make执行或者忽略Makefile的某一部分

5.2.5 函数
    文本处理函数:字符串替换、查找、过滤、排序、统计等
    文件名处理函数:取目录/文件名、前后缀、加前缀/后缀、单词连接等函数
    其它常用函数:if函数、shell函数、foreach函数

5.2.5文件包含
    类似于C语言的#include,使用include命令

5.2.6注释
    使用#开头,表示注释

5.3 规则构成

1. 规则基本构成(由三部分组成)目标目标依赖命令2. 语法格式目标:目标依赖命令注意事项:命令必须使用tab键开头、一般是shell命令一个规则中可以无目标依赖,仅仅实现某种操作一个规则中可以没有命令,仅仅描述依赖关系一个规则中必须有一个目标案例:# Makefile文件中本质就是很多规则构成的,# 规则的语法格式:# 目标:依赖#         shell命令   (注:命令前边必须使用tab键,不可以使用4个空格替换)# 一个规则中可以没有命令,仅仅描述依赖关系all:stu_manager# 如果依赖关系不成立,则继续解析其他的规则,知道依赖关系成立才会执行对应的命令stu_manager:score.o main.ogcc score.o main.o -o stu_managerscore.o:score.cgcc -c score.c -o score.o# 如果依赖关系成立就会执行对应的命令main.o:main.cgcc -c main.c -o main.o# 一个规则中可以无目标依赖,仅仅实现某种操作clean:rm *.o  stu_manager3. 目标详解1》默认目标一个Makefile里可以有多个目标,一般会选择第一个作为默认目标。因此make时默认找寻Makefile文件中的第一个目标执行,当使用“make  目标名”时才会找寻对应的目标执行。2》多目标一个规则中可以有多个目标多个目标具有相同的生成命令和依赖文件案例:# Makefile文件中本质就是很多规则构成的,# 规则的语法格式:# 目标:依赖#        shell命令   (注:命令前边必须使用tab键,不可以使用4个空格替换)# 一个规则中可以没有命令,仅仅描述依赖关系# 第一个目标就是Makefile的默认目标,当执行make时,默认执行的就是默认目标对应的规则all:stu_manager# 如果依赖关系不成立,则继续解析其他的规则,知道依赖关系成立才会执行对应的命令stu_manager:score.o main.ogcc score.o main.o -o stu_managerscore.o:score.cgcc -c score.c -o score.o# 如果依赖关系成立就会执行对应的命令main.o:main.cgcc -c main.c -o main.o# 一个规则中可以无目标依赖,仅仅实现某种操作# 一个规则中可以有多个目标clean distclean:rm *.o  stu_manager3》多规则目标多个规则可以是同一个目标Make在解析时,会将多个规则的依赖文件合并案例:# 多个规则可以是同一个目标# Make在解析时,会将多个规则的依赖文件合并# 最终合并之后的结果为:test : test1 test2test:test1test:test2test1:echo "11111111"test2:echo "22222222"4. 目标依赖1》文件时间戳根据时间戳来判断目标依赖文件是否更新所有文件编辑过,则对所有文件编译,生成可执行程序在上次make之后修改过的C文件,会被重新编译在上次make之后修改过的头文件,依赖此头文件所有源文件都会会被重新编译5. 命令 1》命令的组成Shell命令组成、tab键开头2》命令的执行每条命令,make会开一个进程每条命令执行完,make会检测每个命令的返回码若命令返回成功,make继续执行下个命令若命令执行出错,make会终止执行当前规则,退出3》并发执行命令make -j4  ---》 开辟4个线程执行time make -j4   ---》 显示make执行的时间4》命令同一进程执行命令之间使用分号隔开,并且使用"\"对命令进行连接

5.4 Makefile中的变量

1. 变量基础
2. 变量分类
3. 自动变量
4. 变量的传递1. 变量基础 1》变量定义:变量名 = 变量值2》变量引用:$(变量名)(常用,小括号不能省略) 或者${变量名}2. 变量分类   =   :=  +=  ?=1》:= 立即展开变量变量名 := 变量值 在解析阶段直接对变量赋值2》= 延迟展开变量变量名 = 变量值 在运行阶段,实际使用变量时再进行赋值操作3》追加赋值变量名 += 变量值将变量值追加到变量名原有值的后边,中间以空格隔开案例:var1 = hello# 追加赋值,以空格隔开 var1 += worldall:echo $(var1)4》条件赋值变量名 ?= 变量值 如果变量没有赋值才会进行赋值操作,如果变量已经赋值就不会进行赋值的操作。案例: var1 := hello# 条件赋值, 如果var1变量没有赋值才会进行赋值操作var1 ?= worldvar2 ?= worldall:echo $(var1)echo $(var2)5》注意事项一般在目标、目标依赖中使用立即展开变量在命令中一般使用延迟展开变量3. 自动变量1》自动变量是局部变量,再规则中使用的变量2》目标$@   ----> 表示目标字符串3》所有目标依赖$^  ----> 表示所有的依赖的字符串4》第一个依赖$<   ----> 第一个依赖的字符串5》使用举例gcc  -o $@ $^案例:all:test1 test2echo $@echo $^echo $<test1:echo "test1"test2:echo "test2"
4. 通配符的使用% :模式通配符 ----> 一般用户目标和依赖之间的字符串匹配* :普通的通配符 ----> 一帮用于命令之间的字符串的匹配5. 通过执行make时传递参数给变量进行赋值的操作。make   变量名=变量值  目标名

5.5 Makefile中的函数

5.5.1 函数1:wildcard

 $(wildcard PATTERN) 函数名称:获取匹配模式文件名函数—wildcard
函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。
返回值:空格分割的、存在当前目录下的所有符合模式“PATTERN”的文件名。
函数说明:“PATTERN”使用shell可识别的通配符,包括“?”(单字符)、“*”(多
字符)等。可参考 4.4 文件名中使用通配符 一节。
示例:
$(wildcard *.c)
返回值为当前目录下所有.c 结尾的文件,多个文件名直接使用空格隔开。

5.5.2 函数2:patsubst

 $(patsubst PATTERN,REPLACEMENT,TEXT)
函数名称:模式替换函数—patsubst。
函数功能:搜索“TEXT”中以空格分开的单词,将否符合模式“PATTERN”替换为“REPLACEMENT”。参数“PATTERN”中可以使用模式通配符“%”来代表一个单词中的若干字符。如果参数“REPLACEMENT”中也包含一个“%”,那么“REPLACEMENT”中的“%”将是“PATTERN”中的那个“%”所代表的字符串。在“PATTERN”和“REPLACEMENT”中,只有第一个“%”被作为模式字符来处理,之后出现的不再作模式字符(作为一个字符)。在参数中如果需要将第一个出现的“%”作为字符本身而不作为模式字符时,可使用反斜杠“\”进行转义处理(转义处理的机制和使用静态模式的转义一致,具体可参考 5.12.1 静态模式规则的语法 一小节)。
返回值:替换后的新字符串。
函数说明:参数“TEXT”单词之间的多个空格在处理时被合并为一个空格,并忽略前导和结尾空格。示例:
$(patsubst %.c, %.o, x.c.c bar.c)
把字串串“x.c.c bar.c”中以.c 结尾的单词替换成以.o 结尾的字符。
函数的返回结果是“x.c.o bar.o”

5.5.3 一个普适的Makefile文件

对 test 项目的Makefile文件的改进:引入 wildcard patsubst函数NAME = test
CC = gcc
CFLAGS = -c -g# 将当前目录下的所有的.c文件展开,赋值给变量OBJSs, 多个单词之间使用空格隔开
OBJSs = $(wildcard ./*.c)
#如果有多个.c文件,在不同的路径下,可以在一个OBJSs里用空格分隔,多个路径下的.c文件
#OBJSs = $(wildcard ./*.c ./test/*.c)
#也可以用以下方式连续添加
#OBJSs += $(wildcard ./test/*.c)# 将OBJSs变量中所有以.c结尾的单词替换成.o
OBJS := $(patsubst %.c, %.o, $(OBJSs))# 规则没有命令,只是用来描述依赖关系,
# 第一个目标作为默认的目标
all:$(NAME)# 一个目标可以有多个依赖文件
$(NAME):$(OBJS)$(CC) $^ -o $@
# 模式匹配 : main.o  此时%就表示main字符串
#            lcd.o   此时%就表示lcd字符串# -I ./include  : 从-I参数指定的路径下查找对应的头文件
%.o:%.c$(CC) $(CFLAGS) $< -o $@ -I./include# 规则没有目标依赖,只是为了完成某种操作
# 一个规则中可以有多个目标
clean distclean:rm *.o $(NAME)

反思与总结

总的来说,这周学习内容比较少,主要是shell编程,学习下来我感觉,shell编程还是和C语言很类似的,在逻辑方面shell有它自己的优势,但在书写方面shell要注意的方面要比C语言多,尤其是变量的引用、分支和判断语句的使用和函数的使用方面,逻辑方面不困难,格式稍不注意就容易出错;再就是Makefile编程,复习这一遍下来,差不多理解了,就是在非常多的文件参与编程时,为了简化编译时间,引入Makefile协助编程,Makefile中很多东西都是规定好的,别记混了就行,在多看看通用Makefile文件,理解每一步是干什么的。

写在最后:写这篇文章是笔者一边看老师的目录,一边回想老师讲的内容,仅仅选取了我自己认为比较重要的,或者自己之前没接触过的进行汇总、总结,知识体系不完善,内容也不详细,仅供笔者复习使用。如果是有需要笔记,或者对这方面感兴趣,可以私信我,发你完整的知识体系和详细内容的笔记。写的仓促、水平有限,如有任何错误请多指正,也欢迎友好交流,定会虚心听取大佬的宝贵意见!

华清远见嵌入式培训_第四周回顾与反思相关推荐

  1. 华清远见嵌入式培训_第一周回顾与反思

    目录 第一天 周二 1.1 Linux系统的使用 1.2 终端 1.3 Linux系统命令 1.4 vi编辑器的使用 第二天 周三 2.1 顺利进入("hello world")阶 ...

  2. 华清远见嵌入式培训_第二周回顾与反思

    目录 前言 周一 一.switch..case 1.1 注意事项 1.2 使用练习 二.循环控制语句 2.1 使用goto实现循环 2.2 while循环 2.3 do..while 循环 2.4 f ...

  3. 华清远见嵌入式培训_第三周回顾与反思

    目录 前言 周一 一.函数 1.1 指针函数 1.2 函数指针 1.3 函数指针数组(了解) 1.4 指向函数指针数组的指针(了解) 二.typedef 2.1 typedef的使用 2.2 type ...

  4. 华清远见嵌入式培训_第五周回顾与反思

    前言 这是在华清学习的第五个周末,这一周主要学习的是数据结构.老师说数据结构是一门非常庞大的学科,单单是数据结构里的一个小分支,单拎出来一周都未必可以学透,因此这周的数据结构课程里更多的是思维方向的学 ...

  5. 华清远见嵌入式培训_第六周回顾与反思

    目录 前言 周二 IO简介和标准IO 一.IO简介 1.1 什么是IO 1.2 IO的分类 1.3 什么是系统调用和和库函数 1.4 什么是IO接口 二.标准IO 2.1 fopen/fclose函数 ...

  6. 华清远见嵌入式培训_第七周回顾与反思(上)

    前言 七天的国庆假期已经结束,紧接着的是七天的工作日,前几天的我感叹假期七天有多短,此时此刻的我就感叹七天有多长! 言归正传,本周的前五天课里,紧接着假期前的IO进程课程,第一天学习了:进程中各种常用 ...

  7. 华清远见嵌入式培训---入学

    读者们好,我是华清的一名学员,去年9月报名参加了华清远见的培训,因为本人大四还没有毕业,一直在学校上线上课程,今年2月才加入到了线下班级,在这里想谈一下来到华清半个多月的感受. 首先说一下我为什么培训 ...

  8. linux内核培训广州,嵌入式Linux驱动开发高级培训班-华清远见嵌入式培训中心

    课程目标 本课程以案例教学为主,系统地介绍Linux下有关FrameBuffer.MMC卡.USB设备的驱动程序开发.参加本课程学习的学员,因为具备了Linux设备驱动开发基础,所以本课程针对性较强, ...

  9. 【华清远见嵌入式培训】网络编程(更新中)

    Pre-learning:网络编程 不借助第三方软件实现不同主机.不同操作系统之间的通信.搭建服务器与客户端. Chapter 1 网络发展史与背景 1.1 网络发展简史 ARPnet(阿帕网)因为没 ...

最新文章

  1. 这就是我向您推荐使用Thunderbird邮件客户端的理由
  2. C#读取远端电脑文件的方法
  3. 一文看懂物联网完整产业链条
  4. Python Json序列化与反序列化
  5. 利用预渲染加速iOS设备的图像显示
  6. SQL Server IS NULL语句使用举例
  7. python基础元组(五)
  8. JZOJ 1035. 【SCOI2009】粉刷匠
  9. 一体打印机行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  10. 九大背包问题专题--混合背包问题(状态转移)
  11. Mysql binlog 日志的三种模式
  12. MyBatis generator 注解方式和xml方式
  13. matlab 格式化文件,Matlab 文件格式化/Matlab Source File Formator
  14. PDF论文--字体未嵌入解决办法
  15. 在CMD里进行复制粘贴的方法
  16. 微信服务号开发整体流程
  17. 目标检测入门常见问题(深度学习 / 图像分类)
  18. 单纯形法算法实现--java版
  19. 用文氏图来理解卷积神经网络如何决定提取哪些特征
  20. Combining Word and Entity Embeddings for Entity Linking

热门文章

  1. sql server DATEPART() 函数的使用
  2. CNN-SLAM:学习深度预测的实时稠密单目SLAM
  3. Android Studio Run App 不能自动启动
  4. 数模中常使用的Matlab绘图与Excel绘图
  5. python的取余操作
  6. javascript异步编程系列【一】----用Jscex画圆
  7. 【云计算】云计算、雾计算、边缘计算到底是怎么回事?
  8. 获取行政区划地名地址的简称
  9. php获取N天后的日期,排除周末与节假日加上调休日
  10. Python的GUI图形界面工具列表大全