第十六章 Shell编程

16.1 shell脚本运行

所谓脚本,就是把众多命令写入一个文件中,让其按照一定的逻辑顺序执行,以完成一个具体的功能。而在Linux的shell编译环境下,shell编程与众多编程语言一样,也有其独立的语法。

16.1.1  脚本基本结构

首先,来看一下基本的shell语法格式:

vi  /mnt/test.pl   ---创建脚本文件,注:Linux中脚本一般为.pl或.sh后缀

#!/bin/bash    ---指定编译本脚本的shell

echo  hello      ---输入多条命令

ls  -l  /var/

echo  over

以上就是一个脚本的最简单的案例,其中第一句的#!/bin/bash一般必须书写,至于后面的命令,可以根据个人需求自定义编写。

我们可以看到,脚本编写其实与创建文本文档一样,使用vi即可,编写完毕,它也就是一个文档而已,需要给它增加执行权限才可以当做脚本被执行:

chmod a+x  /mnt/test.pl

有了执行权限,可以直接使用绝对路径调用执行:

/mnt/test.pl    ---执行脚本

16.1.2  脚本执行方式

关于脚本的执行,其实有三种方式可以实现:

方式一: 绝对路径

/mnt/test.pl   ---指定绝对路径执行脚本

或者

cd  /mnt   ---进入脚本所在的目录

./test.pl   --- .表示当前目录

注:本方式要求脚本必须有x权限才可被执行

方式二: 使用shell调用脚本

bash  /mnt/test.pl  ---指定使用bash编译执行脚本

注:本方式,允许脚本文件没有x权限

以上两种方式虽然可以正常调用脚本,但是当脚本中有对环境变量的配置时,会发现脚本的运行未能起作用,如下图:

图中,脚本中对PS1变量做了更改,执行后却未能生效。这是因为Linux中的编译器shell,是允许有多层嵌套的,即多个shell,一个shell的外层再套另一个shell。如下图案例:

图中可见,通过命令更改了PS1变量的值,立即生效了,但输入bash命令后,等于有重新打开了一个shell,该shell嵌套与于原shell之外,环境变量并未改变。当exit退出后,又恢复到了原shell中。

其实,每个shell都会有自己一套完整的、独立的环境变量配置,当打开一个新shell时,所有的环境变量将按系统的默认值初始化,所以新开shell不会受原shell的影响。

因此,前两种脚本的方式,都是新开一个shell执行脚本,脚本执行完毕,新开的shell自动关闭。若在脚本中对环境变量做设置,是不生效的,因为环境变量的设置,对新开的shell执行了,shell一关闭即失效。若要脚本中的环境变量设置立即生效,必须让脚本不开新shell,而在原shell上执行才可以,这就用到了第三种方式。

方式三:

source  /mnt/test.pl

--- source表示使用当前shell编译执行脚本,不开启新shell

.    /mnt/test.pl     --- .表示当前shell,与source功能相同

16.1.3 自定义系统命令

若想让我们自己编写的脚本,像系统命令一样可以随时随地的执行,那么就要把脚本按照系统命令的原理操作。首先,我们知道,系统中的命令大多属于外部命令,执行时都是调用的其可执行程序,使用whereis和which可以查看得到。

那么,按照Linux的命令原理,手动输入的命令,都会去PATH环境变量指定的路径中去寻找命令对应的可执行程序(在环境变量一章中已讲过),可以用echo$PATH查看得到:

系统中所有命令的可执行程序,都是存放于这些路径内的。总结得到,我们可以借助于这种原理,把我们的脚本程序设置为系统命令。

假设有如下脚本:

vi  /mnt/cpuTest.pl

#!/bin/bash

echo start

sar 1  1

echo end

chmod  a+x /mnt/cpuTest.pl

将其设置为系统命令的方式有如下两种:

方式一:

cp /mnt/cpuTest.pl   /usr/bin/    ---复制到系统命令的所在目录下

缺点:自定义脚本与系统命令不分离,难以区分,扰乱原有的系统命令;不便于管理和查找。

方式二:  常用

PATH="$PATH:/mnt"    ---在PATH变量后追加上脚本所在的目录

注:若想让对PATH的设置永久生效,则需要把该命令写入到环境变量配置文件中才可以;脚本名尽量不要与系统中已存在的命令名重复。

16.2 shell编程

以上介绍了脚本的运行,下面来讲解以下具体的编程

16.2.1 变量

关于变量,是所有开发语言必不可少的运行工具,shell编程也不例外。先来解释一下变量的定义:程序运行过程中,用于临时存放数据的一块内存空间即是变量,给这块空间起个名字,即变量名(此定义虽非官方,但很容易理解)。下面来看一下变量的声明、赋值。

shu=5

以此代码为例,是声明了一个变量叫shu,即会在内存中开辟一块空间,给shu专用。=5表示给变量存入数据,即存到内存中,称为 赋值。亦或:name=zhang  也是声明并赋值。

变量的使用也同样是用$符加以提取,如下例:

echo  "my name is: $name"   ---用$提取变量的值,加以使用

另外,当使用变量时,若变量名与之后文件接连书写,没有空格,会造成变量名的识别错误,如:echo $shua,则shell会认为要输出变量shua的值,但如果我们只声明了变量shu,且想要输出变量shu的值呢?可参看下例解决:

shu=5

echo  ${shu}a   ---用{}明确变量名,则输出结果:5a

再来看一下变量的计算,先看如下案例:

可见,代码运行的结果并非我们想象的求和的结果,而是shu3=5+3。这是因为变量赋值时,默认所有数据都当字符类型处理,所以shu1、shu2其实赋值的是字符形态的3、5,所以赋值给shu3时其实仅相当于让三个字符串联而已。

那么,若要想让计算式按数学运算的方式执行,需要使用let关键字,如下例:

shu1=3

shu2=5

let  shu3=$shu1+$shu2    ---let开头的代码,将以数学计算的方式执行

echo  shu3=$shu3      ---此时输出结果为:shu3=8

还有,变量的赋值,也有其他方式。之上的案例中我们可以看到都是在代码中直接给变量赋值的。其实,我们还可以要求人为的从键盘输入数据赋值给变量,如下:

read   shu  ---read表示:要求从键盘输入一个数据,赋值给变量

例如:

图中zhang是我们手动输入的姓名。

再者,我们还可以将命令的执行结果赋值给变量。案例格式如下:

shiJian=`date +"20%y-%m-%d%H:%M:%S"`

注:用反单引号把命令引起来,功能:把命令的执行结果赋值给变量

最后再来看一下变量值的截取,如下例:

shu=abc123

shu2=${shu%%1*}   ---%%表示去除右侧字符,*还是通配符,结果: shu2=abc

shu3=${shu##*c}   ---##表示去除左侧字符,结果:shu3=123

16.2.2 判断语句

说到判断语句,与众多编程语言思路一样,无非是给定一个条件,如果条件满足则执行对应的代码。那么在shell中的格式如下:

if [  条件 ];  then      --- 格式要求:[   ]; 符号左右必须有空格

//代码

fi

运行逻辑:当条件满足、成立,则执行代码,否则不执行代码

虽然逻辑过程容易理解,但是关于条件的书写格式,是比较复杂的,常用格式如下:

[  $shu -gt 20 ];   --- 判断比较数字   -gt 大于  -lt小于   -eq等于  -ge大于等于  -le小于等于 –ne不等于

[  $name = "zhang"  ];  ---用 = 做字符判断,注:=左右无空格,表示赋值功能,=左右有空格,表示判断,!=表示判断不等于

[  -f "/mnt/f1" ];     ---  -f 判断给定的路径是否是一个文件,即判断文件是否存在  -d 判断目录  -l 判断软链接

[-x "/mnt/test.pl" ];   --- -x判断给定的文件是否有执行权限,-r 判断读权限  -w判断写权限

[-z $shu ];     ---判断变量是否为空,即未赋值。若为空,则判断成立

[  条件1  -a  条件2  ];  --- -a表示逻辑与  -o 逻辑或   !逻辑反,即取反值

注:关于满足、不满足,成立、不成立这种对立的判断,称为布尔(bool)型数据,只有两个结果,成立满足叫true , 不成立不满足叫false。

除了这种简单的判断语句,if还有两种格式,如下:

格式2:

if [  条件 ]; then   ---如果条件满足,执行代码1,否则执行代码2

//代码1

else       ---否则,若条件不满足,则执行代码2

//代码2

fi

格式3:

if [  条件1 ]; then   ---如果条件1满足,执行代码1

//代码1

elif [ 条件2 ]; then  ---否则若条件1不满足,判断条件2                    //代码2

elif [  条件3 ]; then    ---如果条件1、2都不满足,判断条件3

//代码3

else      ---若前面条件都不满足

//代码4

fi

好了有了if的三种格式,我们在编程时,就可以依据需求完成不同条件的判断了,来看下面案例:

echo please input your  age

read age

if [  $age -lt  16 ]; then

echo  child

elif [  $age -lt  30 ]; then

echo  younger

elif [  $age -lt  40 ]; then

echo  stronger

elif [  $age -lt  50 ]; then

echo  zhong nian

else

echo  older

fi

以上案例中,根据年龄,逐级判断,输出年龄段状态。值得注意的是,我们排列的条件顺序是从年龄的小到大,那么当年龄大于16岁时回去判断是否小于30,一次类推。但如果我们把条件顺序反过了写,如下:

if [  $age -lt  50 ]; then

echo  uncle

elif [  $age -lt  40 ]; then

echo  stronger

elif [  $age -lt  30 ]; then

echo  younger

elif [  $age -lt  16 ]; then

echo  child

else

echo  older

fi

则我们可以想象到,假设当age=15时,第一个条件小于50的判断是满足的,那么就会直接输出 uncle了,就与我们原先设想的结果完全不同。所以我们一定要先明确一点:只有在前面的条件不满足时,才会去判断后面的条件。在编写多级判断语句时一定要注意判断条件的先后顺序。

好了,下面我们来展示一个综合案例,是一个自制计算器的小程序,大家可以看明白思路后,自行编写试试:

#!/bin/bash

echo"------------------------------"

echo "   welcome to my  calc"

echo"------------------------------"

echo "start"

echo please input the first  num:

read n1

echo please input the second  num:

read n2

echo "please input the fu:+  - *  /  %"

read fu

if [  "$fu" = "+" ]; then

#注:因为fu可能会是*,*又表示通配符概念,所以用""还原回标准字符状态,   #就不具备特殊符号的意义了

let  res=$n1+$n2

elif [  "$fu" = "-"]; then

let  res=$n1-$n2

elif [  "$fu" = "*"]; then

let  res=$n1*$n2

elif [  "$fu" = "/"]; then

let  res=$n1/$n2

elif [  "$fu" = "%"]; then

let  res=$n1%$n2

fi

echo "$n1 $fu $n2 = $res"    #输出最终的计算式,如:1 + 2 = 3

16.2.3  多分支语句

与if…elif…elif…else…fi 类似,shell中还有一个可以实现多层判断的语句,就是case多分支语句。下面是它的格式与思路

case  $变量  in    ---执行逻辑:根据变量的值,找到下面对应的项,执行代码

值1)   代码1  ;;   --- ;; 两个分号,表示本项代码的结束

值2)   代码2  ;;

值3)   代码3  ;;

*)   代码4  ;;   --- * 项表示,变量没有对应的值,则执行*这一项的代码

esac

例如:

echo  "请输入考试名次:"

read mingCi

case $mingCi  in

"1") echo "第一名奖励200元" ;;

"2") echo "第二名奖励100元" ;;

"3") echo "第三名奖励50元" ;;

"*") echo "无奖励" ;;

esac

需要介绍的是,case虽然书写简练,并且也具备多级判断的功能,但是只能做变量值的等值判断,但if…elif语句可以实现变量在区间值(如分数范围,年龄范围等)的判断,所以各有所长,在具体编程时应该在不同时机选择合适的语句。

16.2.4  循环语句

说到循环语句,各种开发语言中都有,shell中用的开发语句主要以while为主。循环语句的功能是:让计算机重复性多次执行某块代码。来看一下while的语法格式:

while [ 条件 ];

do

//代码

done

执行过程:条件判断=>执行代码=>条件判断=>执行代码=>...=>直到条件不满足,所以while语句是先判断,后执行的。

循环语句看似简单,但它的代码执行过程对初学者来说是需要逐步、逐次的思考清楚的,首先来分析一下如下案例:

例:输出100遍hello

shu=1

while  [ $shu  -le 100 ];

do

echo No.$shu  hello

let shu=$shu+1

done

分析以上案例执行过程,变量shu的初始值为1,第一次进入while,先判断shu是否小于等于100,结果为true,那么执行代码,输出一次hell,然后shu自我增加一次(取出shu的值,加1后再赋值给shu)得到shu的值为2,到这里第一次循环结束.然后再次返回判断部分,shu值为2,小于等于100,判断成立,再次进入代码,以此类推。综上,我们可以总结到,循环中必备的有四个内容,我们称为循环四要素。

循环四要素:初值  条件  循环体(即代码)   自更新

有了四要素后,我们写完的代码,可以检查一下是否正确,要避免避免:无循环、死循环的现象。PS:无循环就是第一次条件不满足,直接跳过循环。死循环是循环内没有更新语句,造成判断条件永远成立,致使代码运行到循环后,不再停止、跳出。

好了,再来展示两个案例,以帮助大家理解循环:

例:计算1-100之间各数累加和

shu=1

sum=0

while  [ $shu -le 100 ];

do

let sum=$sum+$shu

let shu=$shu+1

done

echo  $sum

以上案例的思路是按照累加的过程:1+2=3,3+3=6,6+4=10…,所以每次循环累加后,把和存入sum变量,下次循环再次累加。

例:求1-100之间3的倍数之和

shu=1

sum=0

while  [  $shu-le 100 ];

do

let yu=$shu%3

if [ $yu -eq 0 ];  then

let  sum=$sum+$shu

fi

let shu=$shu+1

done

echo  $sum

以上两个案例,读者可以逐一研究代码的执行过程,以理解循环的功能。

再有,循环中还有两个循环控制语句:continue和break,功能如下:

continue  停止本次循环,跳入下一次循环

break     停止、跳出整个循环

案例如下:

例:求1-100之间3的倍数之和

shu=1

sum=0

while  [  $shu-le 100 ];

do

let yu=$shu%3   # %模运算,即求余数的运算

if [ $yu -ne 0 ];  then

let shu=$shu+1

continue

fi

let sum=$sum+$shu

let shu=$shu+1

done

echo $sum

案例中可看到,判断中当shu除以3的余数不为0时,即不是3的倍数,将会进入if语句,自加后执行continue语句,则跳出当前循环,直接进入到了下一次循环判断了,那么后面的累加和操作将不再执行。

例:计算1-100之间各数的累加和,求累加到哪个数时,和到达1000

shu=1

sum=0

while [  $shu =le 100 ];

do

letsum=$sum+$shu

if[ $sum -ge 1000 ]; then

echo $shu

break

fi

let  shu=$shu+1

done

echo $shu

本案例中,当累加和到达1000时,就没有必要继续循环了,所以直接break停止了循环.

以上的所有案例,我们看到都是有固定循环次数的,其实while也可以支持没有固定次数的循环操作,如下例:

jiXu="y"; # 为了满足第一次循环,赋初值为y

while  [ $jixu = "y" ];

do

echo  "上午上课"

echo  "下午实验"

echo  "晚上自习"

echo  "明天继续吗?y/n"

read jiXu

done

另外,shell编程还有for语句结构的循环,它的语法如下:

for  变量  in  值1  值2  值3  ...        do

//代码

done

执行思路:用给定的值,逐一赋值给变量,带入代码执行

缺点:不支持数据范围的指定,如:1-100。PS:若要设定范围需要内嵌特殊代码。

案例:例:计算1-10之间各数累加和

sum=0

for shu  in  1 2 3 4 5 6 7 8 9 10

do

letsum=$sum+$shu

done

echo $sum

16.2.5 选择语句结构

shell中,还有一个独特的语句结构,就是选择结构,这个结构在java、C语言中是没有的,下面来看一下它的语法格式:

select 变量   in  值1  值2  值3 ...

do

//代码

break  ---停止,跳出select结构,若不加break句,会循环重复选择

done

执行思路:把列举的值当做菜单以供选择,根据用户选择,把对应的值赋值给变量,带入代码。

例:

select  xuan in  aaa  bbb ccc  ddd

do

echo your choice is : $xuan

break

done

执行过程如下图:

若没有break语句,则执行过程如下:

如上图,我们只能通过ctrl+c组合键关闭shell进程。

16.3 组合应用

首先,先来看一下变量赋值的一个应用:

图中可见,显示f1中第三列文字,赋值给变量words后,显示变量值时是不分行的,也就说明:当命令结果是多行状态时,赋值给变量后,将变为一行数据,即变量的值中不支持回行。

注:若想在输入命令时,让系统以shell程序的方式执行,则把多行代码用;分隔开即可。

然后,我们再来看一下read读取文档的使用:

read  hang 读取文档中的第一行文字,赋值给变量

但是这个read命令只能读取第一行文字,再次执行还是第一行。原因是因为访问文件时会打开文件,创建文件流,会有指针读取文件的第一行文字,若再次读取,则指针会下移一行,做读取。但是用这个命令时,打开文件,读取一行后立即关闭了文件。再次执行命令,又重新打开了文件,又从第一行开始读取了,所以无法实现多行读取功能。PS:以上原因有过开发经验的读者会比较好理解,虽然不甚准确,但思路接近,比较容易理解,适合于初学者。

那么如果想要读取文件中的每一行文字呢?则需配合while循环来使用,看下例:

shu=1

while  read  hang

do

echo No.$shu: $hang

let shu=$shu+1

done < /mnt/f1

案例功能:逐行读取文档内容,每次读取出一行,赋值给变量,带入代码。

用while配合read使用,则读取完一行后不会关闭文件,进而就可以使指针下移一行,再次读取第二行了。需要解释的是,当read读取成功后,即等于读取操作结果为true,正适合于while的判断;而当读取完文件的最后一行后,再次读取将读取失败,则视为false的结果,所以while循环将停止。运行结果如下图:

好了,在案例中我们也可以看到文件f1原有内容类似于表格,是多行多列的内容,那么我们也可以对每行内容中的每列文件加以单独提取,案例如下:

shu=1

while read  c1  c2 c3

do

echo  No.$shu: $c3

let  shu=$shu+1

done < f1

代码功能:逐行读取文档内容,每次读取出一行,把该行各列的文字,赋值给对应的变量,带入代码,代码中c1 c2 c3是三个变量,对应文件中每行的各列。

16.4 函数调用

16.4.1 函数的定义、调用

当我们需要以一段代码需要多次使用时,如果每次使用都要写一遍代码的话,那么又麻烦,代码又繁琐,那么可以使用函数来实现一次定义,多次使用。

函数,即是一段完整的代码,能够实现一个较小的功能,可以被shell程序所调用。格式如下:

定义格式:

function 函数名() {

代码

}

函数名 (){    ---不写function关键字也可以

代码

}

调用函数:

shell代码中,直接写函数名,即可调用。

案例:

vi  test.sh

#!/bin/bash

function  qiuHe(){

shu=1

sum=0

while [ $shu -le 100 ];

do

let sum=$sum+$shu

let shu=$shu+1

done

echo $sum

}

echo  "我们将要计算1-100之间各数的累加和,结果如下:"

qiuHe    #调用函数qiuHe

值得注意的是:(1)在shell脚本中,程序的开始运行点,并不会从函数开始,而是从函数之外的第一行代码开始执行,所以上例中运行的第一条代码是echo "我们将…"句。(2)还有shell的代码执行过程是由上往下读取到一条语句,即编译一条,所以在函数的编写时,函数的定义语句必须写在调用语句之前,否则函数将无法使用。(3)与其他开发语言不同,shell中的变量并没有严格的生存期概念,只要在之前代码出现使用过的变量,在之后代码中都可以直接使用。

16.4.2 函数的参数传递

当我们调用函数时,如果函数要用到某些数据而自己无法得到,则需要调用方为它提供,这就可以使用参数传递实现。所以参数传递的功能是:调用方,给函数传递素材性数据,让函数使用该素材数据做运算,该素材数据称为参数。

函数中参数定义的格式是:在函数代码中用  $数字  的格式来指定参数的编号、个数,如:$1  $2,若达到10个以上的参数时需用{}明确,如:${10}。调用函数时,只需要在函数名后面列举出要传递进去的数据即可,如下例:

vi test.sh

#!/bin/bash

jiaFa(){

letres=$1+$2   #使用参数,进行计算,参数与调用方给定的一一对应

echores=$res

}

shu1=5

shu2=10

jiaFa  shu1 shu2     #调用函数,并在后面列举出传给它的参数

16.4.3 函数的返回值

反过来想,当函数执行完毕后,如果需要携带数据回到调用方,让调用方使用该数据继续运行,则使用函数的返回值实现。

函数中的书写格式是:在函数代码中用 return 关键字指定带回的返回值,调用方使用 $? 的格式接收返回值。案例如下:

vi test.sh

#!/bin/bash

jiaFa(){

letres=$1+$2

return  $res

}

shu1=5

shu2=10

jiaFa shu1  shu2     #调用函数,并在后面列举出传给它的参数

he=$?   #$?代表之前代码中离的最近的一个函数的返回值

echo $shu1 + $shu2 = $he

16.4.4 小结

通过以上的几个案例可以想到,当一段代码会经常被使用到时,我们可以提前把代码写到一个函数中,那么在之后的shell程序中,如果用到,只需要直接调用就可以了,无需再把代码编写一般,这样就实现了一次定义,多次调用的效果,既节约了代码,又清晰了思路。

另外,关于shell编程部分,初学者可能会感觉有些难度,那么首先要确保能够先理解本章中各案例的每行代码的功能,理解每个案例的执行思路。然后按照每个案例的功能,给自己设计一个类似的案例编写下试试,慢慢积累编程的思路和感觉。关于编程能力的锻炼是需要较多案例演习才能够掌握熟练的。这里为大家提供一个系统用户管理的完整案例以供大家借鉴。

vi  /mnt/userManage.sh

#!/bin/bash

echo"-------------------------------------"

echo "   welcome to user manage system"

echo"-------------------------------------"

echo ""

run=true

while $run

do

select  xuan  in "show all users" "add a new user" "change a user's password" "delete a user" "Exit"

do

case  $xuan  in

"showall users")

allUsers=`awk-F ":"  '{print $1}'  /etc/passwd`

echo  $allUsers ;;

"adda new user")

echo please input a new username:

read name

useradd $name

passwd $name  ;;

"changea user's password")

echo please input a  username forchange:

read name

passwd $name  ;;

"deletea user")

echo please input a  username fordelete:

read name

userdel -r $name  ;;

"Exit")

echo byebye

run=false   ;;

esac

break

done

done

abd shell关闭所有程序_第十六章 Shell编程相关推荐

  1. [go学习笔记.第十六章.TCP编程] 3.项目-海量用户即时通讯系统-redis介入,用户登录,注册

    1.实现功能-完成用户登录 在redis手动添加测试用户,并画出示意图以及说明注意事项(后续通过程序注册用户) 如:输入用户名和密码,如果在redis中存在并正确,则登录,否则退出系统,并给出相应提示 ...

  2. abd shell关闭所有程序_在后台服务器上运行程序

    之前总结过screen的用法,但还可以用nohup命令. nohup工具: Linux系统中有提供一个很好的不挂断地运行命令--nohup.我们使用nohup能很简单的控制使用,在此就简单的介绍一下n ...

  3. abd shell关闭所有程序_一个 Shell 脚本逆袭的规范,拿走不谢

    指定一个默认脚本解释器 "#!" 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell.他指明了当我们没有指定解释器的时候默认的解释器. 为什么建议要在 ...

  4. 我的学习之路_第十六章_xml

    [XML] 可扩展的标记语言 作用:存放数据.配置文件 [XML的语法] xml的文件扩展名必须为: xml xml的内容必须满足以下要求: 1.固定的文档声明 2.合格的元素和属性 3.正确的注释 ...

  5. 奋斗吧,程序员——第十六章 笑渐不闻声渐悄,多情却被无情恼

    y=1/x是x轴的渐近线,在无限遥远的地方无限接近,永远没有交点. 永远没有交点. 就像爱情字典里唱的一样,爱情有一条看不见的界限,我们都过不了那条线. 在没有喜欢的人出现之前,你是我最亲密的人.可是 ...

  6. 第十五章 shell正则表达式

    第十五章 shell正则表达式 见图片 Shell正则表达式 正则表达式的分类 基本的正则表达式(Basic Regular Expression 又叫Basic RegEx 简称BREs) 扩展的正 ...

  7. Windows Shell编程-第十六章.命名空间扩展

    第十六章 命名空间扩展 探测器使用层次结构表述形成系统的许多对象--文件,文件夹,打印机,网络对象等等.这些对象组合定义了一个命名空间,这是一个封闭的符号或名字集合,其中任何给定的符号或名字都能成功地 ...

  8. 微信小程序(第二十四章)- 数据交互前置

    微信小程序(第二十四章)- 数据交互前置 讲解微信小程序前置的原因 参考文档 理解微信小程序 小程序简介 作用 提问 针对提问--uni-app介绍 小程序和普通网页开发的区别 小程序代码构成 文件个 ...

  9. pdfstamper生成pdf无法显示汉字_正点原子STM32F4/F7水星开发板资料连载第四十六章 汉字显示实验...

    1)实验平台:正点原子水星 STM32F4/F7 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载 ...

最新文章

  1. Java Script 第四节课 Java Script的隐式转换
  2. NFS介绍、NFS服务端配置安装配置、 NFS配置选项、 客户端的配置
  3. asp.net FileUpload上传文件
  4. 安装asterisk 时遇到的报错情况,及解决办法。
  5. Java_案例实例1.简单的人机交互
  6. Linux之VMware Tools显示灰色正确解决办法
  7. mysql远程服务器访问数据库
  8. C++中的默认初始化
  9. 爱奇艺视频如何联系客服?爱奇艺联系客服攻略
  10. 拥有这个证书的医务人员恭喜了,国家正式通知……
  11. 图论 —— 2-SAT 问题
  12. Chrome历史版本查看
  13. 植物大战僵尸的闯关关数以及金钱修改
  14. 图的广度优先搜索和深度优先搜索
  15. “踢群第一案”上热搜的背后
  16. 电商系统(毕业设计)
  17. 用Scipy中的linprog解决股票融资中的线性规划问题
  18. 苹果系统简易音乐播放器
  19. POJ 3295: Tautology
  20. VC浏览器相关的学习(四)(在BHO中获取IE版本以及获取窗体句柄)

热门文章

  1. qt输出中文乱码处理(解决方法)
  2. cuSPARSE库:(四)不同矩阵格式在内存中的存储方式
  3. Linux-5.10.13内核完全注释之工作队列
  4. 3d旋转相册代码源码_用代码制作3d相册签到墙(附源码)
  5. python3装饰器例子_Python装饰器几个有用又好玩的例子
  6. u盘安装linux 提示no such device_IGH EtherCAT 开源主站安装及测试
  7. 中怎么均化走线_巴黎世家老爹鞋怎么鉴定真假 辨别真假对比图了解一下
  8. go高性能tcp服务器,在Go中构建并发TCP服务器
  9. git pull git add git commit git branch git更新代码git提交git分支管理
  10. CMake-add_executable()