C高级,终端指令与shell编程以及Makefile入门到精通

目录

一.引言

二.终端指令

2.1 Ubuntu软件的安装

2.2 压缩与解压缩文件

2.2.1压缩文件

2.2.2解压缩文件

2.3 归档和拆包

2.4 文件的操作

2.4.1 cat

2.4.2 wc

2.4.3 find

2.4.4 head和tail

2.4.5 管道符 |

2.4.6 file

2.4.7 查找字符串

2.4.8 剪切字符串

2.5 文件属性的操作

2.5.1文件权限

2.5.2修改文件所属组

2.5.3修改文件所属用户

2.5.4创建链接文件

2.6 用户的操作,增删改查

2.7 磁盘的操作

2.7.1查看u盘是否被Ubuntu识别

2.7.2磁盘分区

2.7.3挂载

2.7.4取消挂载

2.7.5格式化

三.shell编程

四.shell中的变量

4.1变量的定义和使用

4.2shell中的位置变量

4.3命令置换符

5.Linux中的环境变量

六.shell中的数组

6.1定义和初始化

6.2访问数组中的元素

6.3使用数组中的某个元素

6.4数组的拼接

七.shell中的输入输出

7.1输入--->read

7.2输出--->echo

八.shell中的算术运算

8.1 使用 (()) 进行算术运算----->常用于算术运算

8.2 使用$[]进行算术运算

8.3 let进行算术运算

8.4 使用expr 进行运算

8.4.1算术运算

8.4.2关系运算

8.4.3 字符串运算

九.if判断语句

9.1定义

9.2 []或test后跟的参数

9.2.1对字符串:

 9.2.2对数据

9.2.3 对文件

9.3 case ....in 分支语句

十.循环语句

10.1 while循环

10.2 for循环

10.3 select...in

10.4 beak/continue

十一.函数

十二.Makefile 

1.准备工作       

2.Makefile的语法

3.Makefile中的变量

十三.总结


一.引言

        本文总结了c高级所包括的终端指令、shell编程、Makefile的内容,在终端指令中我们将学到Ubuntu中的各种常用指令,包括对文件的操作,磁盘的操作,用户的操作等。shell编程对大部分人来说是一门新语言,但对于接触过其他计算机语言的人来说学习起来还是比较轻松的。最后是Makefile,它相当于是一个管理文件,编译文件的工具,在后期我们使用大量文件的时候,用Makefile会很方便。

二.终端指令

2.1 Ubuntu软件的安装

        在我们用Ubuntu编程的时候会用到各式各样的工具,所以我们需要知道Ubuntu如何在终端安装软件。

1.需要更新软件源,阿里源,清华源,163源等,这里使用的是清华源

清华源地址:清华源

        找到自己Ubuntu的相关版本后复制其中的内容,然后进入Ubuntu,需要对原来的源进行备份,然后将清华源进行替换:

sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak //进行备份,需要管理员权限

vim /etc/apt/sources.list //打开资源文件,进行替换

sudo apt-get update //更换源后要进行更新,注意要联网

注意:如果更新不成功,将https中的s去掉 

关于Ubuntu的网络配置可以看我的上一篇文章:Ubuntu的网络配置

2.操作

安装软件:

sudo apt-get install

卸载软件:

        在平常的生活中,我们卸载软件的时候,如果只是单纯的卸载的话,它的数据其实会有保留的,当你把这个软件下载回来,会继承以前的数据。如果你不需要这些数据可以进行完全卸载的操作。如下:

sudo apt-get remove 软件名 //不完全卸载

sudo apt-get purge 软件名 //完全卸载

下载软件源码:

sudo apt-get source 软件名

        这个操作需要更改sources.list中的内容,将注释的部分全部解除,然后注释掉原来的内容,然后回到终端再进行一次源更新,操作如上。

下载与清除软件安装包:

//下载软件安装包

sudo apt-get download 软件名

下载完安装包后,可以通过dpkg进行离线安装

//清除软件安装包

sudo apt-get clean

2.2 压缩与解压缩文件

2.2.1压缩文件

        压缩文件也是我们经常要用到的一种指令,它分为3种压缩方式:gzip,bzip2,xz

gzip:

格式: gzip 文件名 ----->生成.gz后缀的文件

bzip2:

格式:bzip2 文件名 ----->生成.bz2后缀的文件

xz:

格式:xz 文件名 ----->生成.xz后缀的文件

        在这三种压缩方式中,xz的效率最高,其次是bzip2,最后是gzip,所谓的效率是指压缩过后的文件的大小 xz < bzip2 < gzip,当然效率高的同时三种压缩方式所花费的时间也随之相反,xz > bzip2 > gzip。

2.2.2解压缩文件

        三种压缩方式对应三种解压缩方式:gunzip、bunzip2、unxz。

格式:

gunzip 文件名

bunzip2 文件名

unxz 文件名

2.3 归档和拆包

        上述三种压缩工具是针对文件的压缩,对于目录来说,上述三种方式是不能够进行压缩的。这里就要介绍一种目录压缩方式 tar ,它可以实现对目录的归档与拆包。

归档与归档并压缩:

tar -cf 目录名.tar 目录名 //归档,注意f必须要在最后

在归档的同时我们也可以对归档的文件进行压缩,用上述三种工具实现如下:

tar -czf 目录名.tar.gz 目录名 //用gzip工具进行压缩

tar -cjf 目录名.tar.bz2 目录名 //用bzip2工具进行压缩

tar -cJf 目录名.tar.xz 目录名 //用xz工具进行压缩

 注意:使用的工具参数要与你书写的后缀名一一对应才行,不然进行拆包解压缩的时候会报错。

拆包与拆包并解压缩:

tar -xf 目标文件名

tar -xzf 目标文件名 //对.gz后缀的包进行拆包并解压缩

tar -xjf 目标文件名 //对.bz2后缀的包进行拆包并解压缩

tar -xJf 目标文件名 //对.xz后缀的包进行拆包并解压缩

 注:tar -xf 是万能的拆包解压缩的指令,可以解压任何格式的压缩文件

2.4 文件的操作

2.4.1 cat

        cat可以用来显示文件的内容,也可以用一些参数来进行文件的重定向与追加操作:

cat 文件名  //表示显示文件内容

cat 1.c > 2.c  //将1.c的内容重定向到2.c中,如果2.c不存在就创建2.c并重定向。

cat 1.c >> 2.c  //将1.c的内容追加到2.c中,如果2.c不存在就创建2.c并追加内容。

2.4.2 wc

        wc是对文件的中单词数、字节数、行数的显示,不加参数的时候将会输出上述三种数据。

wc -w 文件名 //显示文件的单词数

wc -c 文件名 //显示文件的字节数

wc -l 文件名 //显示文件的行数

wc 文件名  //显示文件的单词数,字节数,行数

2.4.3 find

        find是查找文件的指令,默认在当前目录下进行查找,如果需要在其他路径下查找,需要添加参数。

find 路径 -name 查找的内容

find test.c //在当前目录下进行查找

2.4.4 head和tail

        head和tail是对单个文件的内容进行按行获取,head是从头开始,tail是从尾开始。

head 文件名 ----> 默认显示前十行

tail 文件名 -----> 默认显示文件的后10行
head -n 文件名 -----> 显示文件的前n行
tail -n 文件名 -----> 显示文件的后n行

head和tail指令,一般不会单独使用,例子:输出文件的第i行  

2.4.5 管道符 |

        管道符的作用是将上一条指令的输出,作为下一条指令的输入:

例如:管道符与head与tail连用,打印文件的后7行的第三行

tail -7 test.c | head -3 | tail -1

2.4.6 file

        查看文件的详细信息

file 文件名
查看文件的详细信息
file a.out ----> ELF类型的,小端存储的可执行文件

2.4.7 查找字符串

        grep 是用来查找一个文件中的字符串的,它有许多参数来进行配合:

grep "查找的字符串" 路径 参数
-n:回显行号
-R:递归搜索
-i:不区分大小写
-w:按单词查找

grep "^helo" ./ -ni ---->开始为hello的字符串
grep "hello$" ./ -ni ----> 结尾为hello的字符串

2.4.8 剪切字符串

        cut ,对于一个有规律的字符串,可以通过cut来进行剪切,如以":"分隔来选取你想要的字符串:

cut -d "分隔符" -f 域 字符串
练习:
把passwd中,ubuntu用户的用户名,描述信息,用户id,组id,组用户,家目录都截取出来。
grep "ubuntu" ./passwd | cut -d ":" -f 1,6

2.5 文件属性的操作

文件的类型:7种

b:块设备文件   c:字符设备文件   d:目录文件   -:普通文件   l:链接文件-->软链接文件

s:套接字文件   p:管道文件

2.5.1文件权限

r--4      w--2     x--1

可读    可写   可执行

        当我们用ls -l 的时候会看到文件的属性,其中最前面的就是文件对于不同组的权限,用rwx来表示,从左到右依次是u(所属用户)g(所属组用户)o(其他用户)分别对应各自的权限。

改变文件的权限:

chmod 通过字母表示法

chmod 通过八进制数

八进制数0-7

例如:chmod 751 test.c

//将test.c 的权限修改为rwxr-x--x 

2.5.2修改文件所属组

chgrp 组用户名 文件名

2.5.3修改文件所属用户

chown 用户名 文件名

chown ubuntu: test.c    #把test.c的文件所属用户和文件所属组用户都改成ubuntu
chown ubuntu:root test.c  #把test.c的文件所属用户改成Ubuntu,文件所属组用户改成root
chown :root test.c   #把test.c的文件所属组用户改成root
chown root test.c        #把文件所属用户改成root

2.5.4创建链接文件

硬链接:

        创建了硬链接------> 可以理解为复制了一份,没有重新开辟内存,如果硬链接文件中的内容,修改了那么源文件的内容也会被修改,源文件和硬链接文件中的内容是保持一致的。

ln 绝对路径/文件名 绝对路径/连接名

软链接:

        创建软连接------> 可以理解为快捷方式,如果源文件被删除,则链接断开,再重新创建一个同名的源文件,就会重新链接。

ln -s 绝对路径/文件名 绝对路径/链接名

 当相对路径创建软连接时,如果源文件路径改变,链接文件就会失效。

2.6 用户的操作,增删改查

1.创建用户

sudo adduser 用户名 -----> 超级用户才能添加用户或者组

2.给用户添加sudo权限

sudo vim /etc/sudoers

进入文件后添加一行:

目标用户 ALL=(ALL) ALL

3.查看当前用户

whoami 

4.查看用户的ID号

id 用户名

5.删除用户

sudo deluser 用户名 ------> 不会删除用户的家目录,rm -r /home/用户名

sudo userdel -r 用户名 ------>删除用户及用户的目录

6.修改用户的详细信息

        修改用户信息的前提是,要修改的用户,在当前开机之后没有登陆过。

sudo usermod -c 999 ubuntu  #修改用户的描述信息,修改的是开机时候的名字
sudo usermod -m -d /home/hello ubuntu 
#把Ubuntu用户的家目录,改为/home/hello
sudo usermod -g 目标组 用户名
#修改用户的所属组为目标组
sudo usermod -l hello ubuntu
#修改用户Ubuntu的名字为hello

7.通配符

*:匹配一个或者多个字符
?:匹配一个字符
[]:1)[1-6]:匹配1-6当中的任一个字符
   2)[1234]:匹配1,2,3,4中的任一个字符

   3)[1,2,3,4,f,t,c]:匹配当中任意一个字符

2.7 磁盘的操作

2.7.1查看u盘是否被Ubuntu识别

ls /dev/sd*

如果有结果说明识别成功

2.7.2磁盘分区

sudo fdisk /dev/sdb

m可以提示帮助信息,

d删除分区

n新建分区,每一步默认就可以

p打印分区

w:将操作写入磁盘并退出

q:直接退出

2.7.3挂载

sudo mount /dev/sdb1 ~/udisk

                          |               |

    要挂载的磁盘分区    挂载在Ubuntu中的位置/要保证位置存在

挂载成功后,对Ubuntu中目录的操作就相当于对磁盘的操作。

2.7.4取消挂载

sudo umount ~/umount -----> 直接加要取消的要挂载的位置

取消挂载后也不会影响之前存入的内容

2.7.5格式化

sudo mkfs.两次tab键可以显示出文件系统格式 /dev/sdb1

通常格式化为ext4/ntfs

三.shell编程

         程序语言有编译型语言和解释型语言,shell属于解释型语言。对于大部分人来说shell是一门新的语言,但学过其他程序语言的话会很好上手。

1 shell使用的解析器

bash ----> Ubuntu用的解析器

sh -----> 开发板常用的

2 第一个shell脚本

#!/bin/bash    
#写明解析器

#打印hello world
echo "hello world"

 第一行可以不写

3 执行脚本文件

        1)修改文件权限

       shell脚本默认是没有执行权限的,这时候可以通过chmod来进行权限的修改,就可以执行了

chmod 777 hello.sh   #让hello.sh变成一个可执行的脚本文件
./hello.sh     #执行脚本文件

        2)bash 脚本文件

        bash 是shell脚本所用的解析器

 bash hello.sh    #不需要修改文件权限

#其实是在后台打开了另一个终端,把结果返回到当前终端

        3)source 脚本文件

source hello.sh  #不需要修改文件权限

#当前终端解析指令,在当前终端返回

shell练习:

在脚本文件中完成以下操作: 1.在自己的用户主目录下新建两个子目录subdir1 subdir2 2.将/etc/passwd文件拷贝到subdir1,将/etc/group拷贝到subdir2 3.将subdir2重命名为subdir 4.对subdir1进行打包并且压缩成xz格式 5.将打包后的xz格式文件拷贝到subdir目录下 6.解压subdir目录下的压缩格式文件 7.查看subdir目录下所有的文件,在subdir目录下搜索ubuntu字符串并打印行号,不区分大小写

四.shell中的变量

4.1变量的定义和使用

1、在shell脚本中没有数据类型的说法,只有字符串

定义变量的格式:

变量名=变量的值

变量名='变量的值'

变量名="变量的值"

2、变量名的命名规范,和C语言中一致。

3、定义变量时等号的两侧都不能加空格

4、使用变量

$变量名

${变量名} (推荐使用)

5、使用已有的变量给新的变量赋值

#!/bin/bash

#定义变量
a=10  #定义了一个变量a值为10
b='2 3'  #定义了一个变量b值为2 3
#c = 9  #error  等号两侧不能加空格
c=hello

#打印变量
echo ${a}
echo ${b}
echo ${c}

#使用已有的变量给新的变量赋值如果带空格需要使用""
#d=${c} world   #error
d="${c} world" 
#f='${c} i' 
echo ${d}
#echo ${f}   ${c} i

f=${c}
echo ${f}

4.2shell中的位置变量

$0   ----> $n
$1
$2
....
${10} ----> 9之后需要用{10}

 位置变量获取的是终端输入的值,也有在之后for循环的时候用到。

4.3命令置换符

        我们在shell脚本中是可以运行终端指令的,如果我们要将终端指令的值赋给一个变量,那么就需要命令置换符,而不是直接赋值。 

把指令运行的结果赋给变量。
#!/bin/bash
a=`ls`   #把ls的结果赋值给a
echo $a
b=$(ls ~)   #把ls ~的结果赋值给b
echo $b

echo -n 输出的内容 ---->输出但是不换行

5.Linux中的环境变量

        配置环境变量的作用是将一个文件夹放到可执行区域,然后就能直接执行该文件夹中的脚本

方法1:临时生效

export PATH=${PATH}:/home/ubuntu
                    |                       |
              环境变量        追加的值
只对当前终端有效,退出终端就不生效了

方法2:修改/etc/bash.bashrc(常用)

在文件的最后添加语句
export PATH=${PATH}:/home/ubuntu      把Ubuntu添加到环境变量中
使配置生效
1、重启
2、source /etc/envirnment
特点:对所有用户都生效

方法3:修改家目录下的.bashrc 文件

在文件的最后添加语句
export PATH=${PATH}:/home/ubuntu把Ubuntu添加到环境变量中
使配置生效
1、重启
2、source /etc/envirnment
特点:只对当前用户生效

六.shell中的数组

6.1定义和初始化

数组名=(数组的值)
#初始化
数组名=(元素值 元素值 元素值 元素值 ····)
数组名=([下标]=元素值 [下标]=元素值 ····)
#第二种初始化方式,元素的个数就是具体值的个数

6.2访问数组中的元素

${arr[下标]}  -----> 一定加{}

6.3使用数组中的某个元素

${arr[*]} -----> 全部元素
${arr[@]} -----> 全部元素

#个数相关
${#arr[*]} -----> 全部元素的个数
${#arr[@]} -----> 全部元素
${#arr[0]} -----> 打印arr[0]元素的长度

6.4数组的拼接

数组名=(${arr[*] $brr[*]})  #本质也是数组初始化

七.shell中的输入输出

7.1输入--->read

read var1 ----> 从终端读入把值赋给var1
read -p "提示字符" 变量名 ------> 输出提示字符
read -t  5 var1 ---->控制时间,5秒内不输入内容自动结束

read -n 3 var1  ----->控制位数,超过n位自动结束输入
read -s var3  ----->终端输入不显示,类似于输入密码
echo ${var3}

7.2输出--->echo

  1. echo默认不解析转义字符加参数-e解析转义字符

  2. -n取消换行

例:

#!/bin/bash
a=hello
#echo $a world  --->hello world
echo '$a world' # '' 可以用在变量的值有空格并且只有赋值操作
echo "$a world"
b=hi
echo $a $b
echo '$a $b'
echo "$a $b\n"  #echo默认不解析转义字符
echo '${a} ${b}' #变量不会被展开
echo -ne "${a} ${b}\n" #-e解析转义字符

八.shell中的算术运算

8.1 使用 (()) 进行算术运算----->常用于算术运算

        1.格式: ((表达式)) 例:((2+6))

        2.在(())中使用变量时,可以加$也可以不加(推荐加)

        3.使用表达式的值,需要加$,变量名=$(())

        4.运算符两边可以加空格,也可以不加空格。

        5.((变量名=表达式)),可以直接在小括号内进行赋值操作

        6.(())内,支持C语言的语法,可以完成复杂的运算

        7.支持自增自减运算,不需要转义

#!/bin/bash
#(()),里面可以放多个表达式,取最后一个表达式的结果---逗号运算
sum=$((1+2,3+4,7+9))
echo $sum

read -p "请输入:" a b
echo $((a+b))
echo $((a-b))
echo $((a*b))  #(())中*不需要转义
echo $((a/b))

8.2 使用$[]进行算术运算

        1.格式:变量名=$[表达式1]

        2.使用变量可以加$,也可以不加

        3.运算符两边可以加空格,也可以不加空格。

        4.必须使用变量接收表达式的结果 ----> $[]不能单独存在

#!/bin/bash
a=9
b=7
c=$[a + b]
#$[]不能单独存在,需要使用变量接收或者打印
#$[$a-$b]
echo $c
#echo $d

8.3 let进行算术运算

        1.格式:let 变量名=表达式

        2.运算符两侧不能加空格

        3.使用变量的时候,可以加$也可以不加$

        4.let必须放在表达式起始的位置

#!/bin/bash
a=9
b=7
let c=a+b
echo $c

8.4 使用expr 进行运算

8.4.1算术运算

  1. 格式:expr 表达式

  2. 运算符两侧必须加空格

  3. 使用变量时必须加$

  4. expr不能进行,自增和自减运算

    expr $a++ #error

    expr $a + 1 #OK

  5. 在expr中使用某些字符的时候需要转义,\

  6. 如果想把expr的运算结果赋值给变量,需要使用命令置换符

  7. expr可以执行更多的运算。

  8. expr本质是一个指令

使用expr计算下面表达式的结果,并赋值给变量a

3*(2+1**4/3)

由于expr不支持幂运算,所以把1**4改成 1*4

#!/bin/bash
a=$(expr 3 \* \( 2 + 1 \* 4 / 3 \))

echo $a

8.4.2关系运算

expr ARG1 | ARG2
    如果arg1不为0/arg1和arg2同时为真,输出arg1的结果
    如果arg2为真,arge为假,才输出arg2的结果
expr ARG1 & ARG2
    如果两个都为真输出agr1的结果,如果有一个为假,结果为0
expr ARG1 < ARG2
expr ARG1 <= ARG2
expr ARG1 = ARG2
expr ARG1 != ARG2
expr ARG1 >= ARG2
expr ARG1 > ARG2
              结果为0/1

#!/bin/bash
a=10
b=20

echo -n "a | b ="
expr $a \| $b
echo -n "a & b ="
expr $a \& $b
echo -n "a < b ="
expr $a \< $b
echo -n "a > b ="
expr $a \> $b
echo -n "a != b ="
expr $a != $b

8.4.3 字符串运算

expr match 目标字符串 输入的字符串    

#判断两个字符串,是否有一个可以作为另一个的子串,返回子串的长度,返回配完全成功的个数

注意:2个字符串是从头开始比较的,返回从头开始2个字符串有几个元素相同     

str=hello

expr match "$str" "h"        

expr substr 主字符串 开始位置 截取长度 #截取子串

#截取字符串,如果截取长度超过了字符串的长度,把字符串剩余的部分全部截除

expr substr "$str" 2 8

expr index 主字符串 查询的字符 

#返回单个字符在字符串中第一次出现的下标

expr index "$str" "i"

 expr length 字符串   #返回长度

expr length "hi"

练习:
通过read读入一个网址,将网址赋值给一个数组,如下: 使用expr以.为界限,截取字符串放入到数组中并输出 arr[0]=www arr[1]=baidu arr[2]=com 注:不能用cut  

九.if判断语句

9.1定义

if [ 表达式 ] #单分支
then
    shell语句
fi

if [ 表达式 ] #双分支
then
    shell语句
else
    shell语句
fi

if [ 表达式 ] 

then

        shell 语句

elif [ 表达式 ]

then

        shell 语句

fi

注:[] 表示的是test  所以if判断也可以写成  if test 表达式,如果要用[] 则括号前后必须有空格

9.2 []或test后跟的参数

9.2.1对字符串:

        -a  :判断2个表达式是否同时为真

        -o  :任意一个表达式为真

        -n  :判断字符串不为空

        -z  :判断字符串为空

        =  :判断2个字符串是否相等

        !=  :判断2个字符串不相等

#!/bin/bash
#read str
#if [ -z $str ]
#then
#    echo "str为空"
#else
#    echo "str不为空"
#fi

#判断字符串的大小关系,按位判断,遇到不同的就比较
str=hello
str1=hell
if [ "$str" == "$str1" ]
then
    echo "str==str1"
else
    echo "str!=str1"
fi

 9.2.2对数据

        -eq : 相等

        -ge : 大于等于

        -gt  : 大于

        -le  : 小于等于

        -lt  : 小于

        -ne : 不等于

#!/bin/bash
a=100
read b
#对于数据元素的操作
if test $b -ge $a
then
    echo "b>=a"
    if test $b -eq $a
    then
        echo "b=a"
    else
        echo "b>a"
    fi
fi

9.2.3 对文件

        对文件的操作只列举几个,具体可以通过man test 去查看详细信息

        -b,是否为块设备文件

        -L,是否为链接文件

        -f,判断是否为普通文件

        -r:判断文件是否存在,是否有可读权限

        -w:判断文件是否存在,是否有可写权限

        -x:判断文件是否存在,是否有可执行权限

9.3 case ....in 分支语句

case ${变量名} in
    表达式1)
        shell语句
        ;;       ---->相当于switch···case里面的break,;;必须写出来
    表达式2)
        shell语句
        ;;     
        ·····
    *)      ---->最后一种情况,不需要加;;
        shell语句
esac

表达式可以是常量
    Y|yes|y|YES) ---->匹配四个字符串中的任一个
    [1-6]) -----> 匹配1-6中的任一个字符
    *}  ---->相当于switch···case中的default,但是作为一个通配符,*放置的位置会影响执行的效果。

十.循环语句

10.1 while循环

while [ 表达式 ]   ----> while [ 表达式 ] ; do
do
    shell语句
done

while true  -----> while(1)
do
    语句块
done

10.2 for循环

第一种:
for ((i=0;i<8;i++))
do
    shell语句
done

第二种:
for 变量名 in aa bb cc   --->in后面是i可以出现的内容,控制循环次数
do
    shell语句
done

seq队列 ----> 是一条指令,可以和for结合使用,一般放在in后面的位置
seq 起始值 间隔值 终止值

for 变量名 `seq 1 1 10`

do 

        shell 语句

done
可以使用命令置换符,获取seq的结果。

10.3 select...in

1.格式:

#!/bin/bash
select var in aa bb cc dd
do
    echo $var
done


#运行效果
ubuntu@ubuntu:day4$ bash sele.sh
1) aa
2) bb
3) cc
4) dd
#?       --->提示输入
          ---->可以输入具体的数字,选择某一项
          ---->如果什么都不输入直接回车,再输出提示

2.与case...in结合使用

#!/bin/bash
select var in ubuntu windows macos redhat
do
    case $var in
        "ubuntu")
            echo "使用的是Ubuntu系统"
            ;;
        "windows")
            echo "使用的是win系统"
            ;;
        "macos")
            echo "使用的是mac系统"
            ;;
        "redhat")
            echo "使用的是redhat系统"
            ;;
    esac
done

10.4 beak/continue

1、break n  ----->跳出n层循环
break 1  ----> 跳出一层循环,1可以不写
break 2  ----> 跳出两层循环

2、continue n  ----->跳出n层本次循环
continue 1   ----> 跳出一层本次循环,1可以不写
continue 2   ----> 跳出两层本次循环

continue跳出n层本次循环

十一.函数

格式:

function 函数名()
{
    shell语句
}

1>shell中定义函数时,可以不加function,也可以加function,推荐加
2>shell中没有参数列表,具体根据调用的格式决定
3>shell中函数没有返回值类型,具体根据函数内部书写格式决定
4>shell中仍然遵循,先定义后调用的规则,但是shell中,函数的定义和声明不能分开,只能把函数定义在函数调用的上方
5>shell函数中的变量,是全局变量

2.参数获取

        shell中的函数是没有设定参数的,我们用$1.....$n来表示传入进函数的参数。

通过位置变量获取参数
$1····$n---->9以上${10}
$#传参个数
$* $@ 所有参数 

3.返回值

        用return返回值只能返回[0-255]之间的数,如果想要获取这之外的数就需要用一个变量去接收。函数的调用是函数名后接参数

只能返回[0-255]之间的数
sum=9
#readonly sum=9   #readonly修饰的变量不能被清空
#echo $sum
#unset sum
#echo $sum
#local a=8
#echo $a
#function add()
#{
#    return $(($1+$2))
#}
#add $1 $2
add()
{
    echo $(($1+$2))
}

sum=`add 255 9`   #只能返回[0-255]之间的数
#如果想计算,超过255的数,就不能返回结果
#可以使用echo打印,如果相接收,使用命令置换符接收

a=`echo $sum`
echo $sum

十二.Makefile 

        Makefile是一个工程项目管理工具,对于大工程而言,我们会创建非常多的文件,这时候我们需要通过Makefile工具来进行文件管理。

1.准备工作       

首先我们需要对编译有一个详细的了解:

  1. 编译过程

  2. 变量基础

  3. 目标和依赖的思想

预处理    编译    汇编    链接
gcc -E .c -o .i
gcc -S .i -o .s
gcc -c .s -o .o  --->Makefile
gcc .o -o exe

2.Makefile的语法

        Makefile由规则和依赖组成,其中也可以定义变量,规则的构成:目标 依赖 命令:

一个目标可以没有依赖,可以没有命令
一个目标也可以有多个依赖
一个规则必须有一个目标

        Makefile把程序的执行分为两步

源文件----->汇编文件
汇编文件----->可执行文件


当文件发生修改,Makefile会根据,文件的时间戳判断文件是否更新,再决定是否重新编译。

初始版Makefile:

all:hello

hello:main.o hello.o
    gcc main.o hello.o -o hello
main.o:main.c
    gcc -c main.c -o mian.o
hello.o:hello.c
    gcc -c hello.c -o hello.o

        生成一个hello的可执行文件,hello通过 main.o 和 hello.o 编译生成,main.o由main.c编译生成,hello.o由hello.c编译生成。

3.Makefile中的变量

        可以理解为宏定义,变量的概念赋值:

=:延迟赋值
+=:追加赋值
:=:直接赋值
?=:条件复制 ----->如果变量前面有值就不赋值

 第二版Makefile:

        我们运用到了上面提到的变量,将目标赋值给一个变量,依赖赋值给另一个变量,通过在Makefile中进行调用,可以减少我们的维护工作:

CC = gcc
EXE = hello
OBJS += main.o
OBJS += hello.o

#引入%通配符
#自动变量$@,$^,$<是针对一条规则而言的

#$@ 表示所有目标

#$^ 表示所有依赖

#$< 表示第一个依赖


#规则:目标、依赖和命令构成
all:${EXE}

${EXE}:${OBJS}
    ${CC} $^ -o $@
main.o:main.c
    ${CC} -c $^ -o $@
hello.o:h.c
    ${CC} -c $^ -o $@
#会检查文件的时间戳
clean:
    rm *.o ${EXE}

4.引入通配符

%     ------> 目标和依赖之间的唯一匹配

最终版Makefile:

        这里通过%来通配.o和.c文件,Makefile会根据你变量中的依赖进行一一对应:

CC = gcc
EXE = hello
OBJS += main.o
OBJS += hello.o

#引入%通配符
#自动变量$@,$^,$<是针对一条规则而言的
#规则:目标、依赖和命令构成
all:${EXE}

${EXE}:${OBJS}
    ${CC} $^ -o $@
%.o:%.c
    ${CC} -c $^ -o $@
#会检查文件的时间戳
clean:
    rm *.o ${EXE}

十三.总结

        这就是本次c高级部分的全部了,总的来说知识量还算挺多的,主要是shell编程的部分,还需要多加的练习,Makefile是我们C语言程序员必须要掌握的一项技能,以便于后期代码的维护。感谢阅读本文! 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值