一、shell的初步理解 1、怎么理解shell shell-->翻译成中文:贝壳,在贝壳内部就是Linux内核,在shell外部就是用户层。所以shell就是用户和内核之间的媒介。 2、shell命令 shell命令就是Linux命令,大多数的Linux命令都是存放在/bin 1》打开一个Terminal终端 --》实际就是运行了一个进程gnome-terminal-server gec 2579 1837 0 1月11 ? 00:00:58 /usr/lib/gnome-terminal/gnome-terminal-server 2》打开终端后,会运行一个进程bash,bash是进程gnome-terminal-server的子进程 gec 3951 2579 0 1月11 pts/19 00:00:00 bash gec 18432 2579 0 09:38 pts/4 00:00:00 bash 3》所有执行的程序都是bash的子进程,bash是一个程序解析器 gec 18506 18432 0 09:41 pts/4 00:00:00 ./hello gec@ubuntu64:~$ which bash /bin/bash 二、shell编程 1、什么是shell编程 shell编程就是脚本编程,使用shell的语法把需要执行的文件组织起来。运行脚本文件就可以直接运行这些程序 2、C语言和shell编程的区别 C语言程序 shell编程 --------------------------------------------------- 语法: C语言语法 shell语法 是否需要编译: 是 否 文件后缀 : .c .sh 文件的存放的位置:Linux任意目录 一般放在Linux环境下 三、C语言程序与shell脚本文件运行方式 1、C语言输出helloworld 1>编辑工程文件: vi hello.c 2>编译工程文件: gcc hello.c -o hello 3>运行程序 : ./hello 2、shell脚本文件输出helloworld 1>编辑脚本文件 : vi hello.sh 2>更改权限 : chmod 777 hello.sh 3>执行脚本文件 : ./hello.sh 四、shell脚本的hello world程序 标准的脚本文件格式: hello.sh --------------------- #!/bin/bash --》指定bash解析器的路径 echo "hello world" --------------------- echo命令的用法: echo - 显示一行文本 SYNOPSIS(总览) echo[OPTION]... [STRING]... DESCRIPTION(描述) 允许在标准输出上显示STRING(s). -n 不输出行尾的换行符. -e 允许对下面列出的加反斜线转义的字符进行解释. -->解析转义字符 ---------------------------- 注意:脚本文件一般需要加bash解析器的路径 ===================================== 练习: 1、打印输出 : 2021/1/12 GZ2021 hello world 2、打印输出: 2021/1/12 GZ2021 hello world 示例代码: #!/bin/bash echo -e "2021/1/12\tGZ2021\thello\tworld" echo -e -n "2021/1/12\nGZ2021\nhello world\n" ========================================= 五、shell脚本变量的定义 1、变量的分类 1》自定义变量 2》系统环境变量 PATH -->执行程序,如果没有写程序文件路径。默认去PATH设置的路径去找 LD_LIBRARY_PATH -->调用动态和静态库时,如果不在当前路径下,就会去LD_LIBRARY_PATH设置的路径下找这个库 export PATH=$PATH:/home/gec export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/gec 2、变量的命名规则类似于C语言 由数字、下划线、字母组成,只能由下划线或字母开头 3、shell里面的变量是不需要定义数据类型 c语言: int a=100; shell: a=hello a=100 4、打印变量的值: a=hello --》定义一个变量a赋值等于hello字符串,等号左右两边都不可以加空格 echo a --》打印a这个字符串 echo $a --》打印a的值 输出结果 gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ ./test1.sh a hello 5、命令行传参 C语言:argc表示参数个数,argv参数列表第一个参数地址 gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ cat hello.c -n 1 #include 2 3 int main(int argc, const char *argv[]) 4 { 5 printf("argc:%d\n", argc); 6 7 int i; 8 for(i=0; iargc、 argv $# -->表示除了脚本文件名之外的参数个数 $* -->除了脚本文件名之外的所有参数 示例代码: gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ cat test2.sh #!/bin/bash echo $# echo $* echo $0 echo $1 echo $2 echo $3 echo $4 执行结果: gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ ./test2.sh aaa bbb ccc 3 aaa bbb ccc ./test2.sh aaa bbb ccc 注意: $# -->运行脚本文件时的参数个数(不包括执行文件名) $* -->运行脚本文件时的传递的参数 $0 -->运行脚本文件时的执行文件名 $1 -->运行脚本文件时的传递的参数的第一个参数 $2 -->运行脚本文件时的传递的参数的第二个参数 $3 -->运行脚本文件时的传递的参数的第三个参数 $4 -->运行脚本文件时的传递的参数的第四个参数 $? -->表示最后一行命令执行结果返回值,shell命令执行成功,返回$?等于0,否则非0 ================================ 执行脚本文件: 如果第一个参数是 hello, 打印hello 1, 打印hello1 ---------------- 练习: 1、写一个脚本文件,实现终端打开后,输出一个"欢迎登录ubuntu" gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat excise1.sh -n 1 #!/bin/bash 2 3 echo "欢迎登录ubuntu" gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat ~/.bashrc -n 121 cd /mnt/hgfs/课堂笔记/09\ shell编程/02/code 122 ./excise1.sh 123 124 cd ~ 2、打开终端,自动执行一个打印hello world的程序 gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat ~/.bashrc -n 124 cd ~ 125 ./hello ======================================= 六、shell编程符号 1、双引号 ---》作用:把某些字符串变成值 a=hello a = hello -->错误的,语法不支持,赋值号前后不能加空格 a="hello" a= "hello" -->错误的,语法不支持,赋值号前后不能加空格 a=hello world -->错误的,语法不支持,字符串有空格必须加双引号 a="hello world" str=$a good -->错误的,语法不支持,字符串有空格必须加双引号 str="$a good" 把Linux命令和字符串组合 str="today is `date`" --》把命令date实际结果输出 :today is 2021年 01月 12日 星期二 14:29:54 CST echo $str 2、单引号 ---》把所有括住内容变成字符串 str='today is `date`' --》Linux命令会失效输出结果:today is `date` str='today is $a' --》变量调用也会失效输出结果:today is $a echo $str 3、反引号 --》把Linux命令从字符串标识出来,当作Linux命令执行 str="today is `date`" --》把命令date实际结果输出 :today is 2021年 01月 12日 星期二 14:29:54 CST echo $str 注意:遇到单引号会失效 4、重定向符号 大于号> (write写数据到文件) 小于号< (read读文件数据) 标准输入文件描述符:0 标准输出文件描述符:1 标准出错文件描述符:2 (1)标准输出(1)重定向: echo "hello world">1.txt echo "hello world" > 1.txt echo "hello world" 1 > 1.txt ls >1.txt 把标准输出重定向到1.txt,把ls命令的输出结果导入1.txt ls 1>1.txt (2) 标准出错(2)重定向 5.txt文文件不存在,则ls命令执行报错 gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ ls 5.txt ls: 无法访问'5.txt': 没有那个文件或目录 gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ ls 5.txt >1.txt --》命令默认把标准输出重定向到1.txt(失败成功) ls: 无法访问'5.txt': 没有那个文件或目录 gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ ls 5.txt 2>1.txt --》命令把标准出错重定向到1.txt(执行成功) 例子: gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ ls 1.sh 1.txt 2.sh 3.sh 4.sh excise1.sh UDP服务器和客户端同时接收和发送 gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ ls 5.txt 1>1.txt ls: 无法访问'5.txt': 没有那个文件或目录 gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat 1.txt --》说明没有导入成功 gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ ls 5.txt 2>1.txt gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat 1.txt ls: 无法访问'5.txt': 没有那个文件或目录 (3)标准输入(0)重定向 写一个C语言代码: gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ cat fgets.c -n 1 #include 2 3 int main() 4 { 5 char buf[20]; 6 fgets(buf, 20, stdin); //==>read(0, buf, 20); 7 printf("buf:%s\n", buf); 8 return 0; 9 } 执行结果 gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/01/code$ ./fgets <1.txt --》把原本从键盘文件获取数据重定向成从1.txt文件取数据 buf:hello world 5、管道 | --》就算不是文件也可以实现类似重定向的效果 wc --》命令:用来计算字符串的行数、单词个数、字符个数 ls -l | wc ---》把ls -l 的输出当作wc命令的输入 ====================== 七、字符串的处理 1、计算字符串的字符个数 str=helloworld2124goodboyhelloworld123456789 echo "${#str}" --->40 通配符: * 代表任意长度的任意字符 ? 代表一个长度的任意字符 [a-z]: 代表一个长度的a-z之内的字符 [az]: 代表一个长度,只能匹配a或者z的内容 [^az]: 代表一个指定范围a/z之外的字符 与[az]相反! %: 从右到左尽可能匹配少的字符 %%: 从右到左尽可能匹配多的字符 #: 从左到右尽可能匹配少的字符 ##: 从左到右尽可能匹配多的字符 2、删除字符串 str=asdfahelloworld2124goodboyhelloworld123456789 (0)删除右边字符串 只想要:asdfahelloworld 命令: echo "${str%2124*}" (1)删除左边字符串 echo "${str#*hello}" ---> 把str的字符串从左往右找到hello后,把hello前面的所有字符串和当前hello全部删掉 输出结果: world2124goodboyhelloworld123456789 (2)删除左边字符串 echo "${str##*hello}" ---> 把str的字符串从左往右找到最后一个hello后,把最后一个hello前面的所有字符串和当前hello全部删掉 输出结果: world123456789 ============================= 练习时间: (1)字符串: str=hello345acbcq345weqapplewyeatreescgaf230helloappletree111 要求: 1. 计算长度 --》echo "${#str}" 2. weqapplewyeatreescgaf230helloappletree111 -->echo "${str##*345}" 3. hello345acbcq345weqapplewyea -->echo "${str%%tree*}" 4. yeatree --> str1="${str%scg*}" echo "${str1#*lew}" (2) 字符串: str=111111230a111111230b111111230t111111 1. 111111230a111111 -->echo "${str%230b*}", echo "${str%%230[bt]*}", echo "${str%%230[^a]*}", echo "${str%%230[b-t]*}" 2. 111111230b111111230t111111 -->echo "${str#*230a}" ================================ 八、测试语句(判断语句、test语句) 例子: 判断命令行传参参数是否等于2($#) if [ $# -ne 1 ] ; --->记住: [ 和 ] 左右两边必须加空格 then echo "please input two argument" fi 也可以写成 if test $# -ne 1 then echo "please input two argument" fi 注意:只要[ ]里面的语句成立就执行,返回值为0时才执行 ============================== 九、分支控制语句 C语言: 分支语句:if-else if-else switch 循环语句:while do-while for shell: 分支语句:if-elif-else case 循环语句:while until for 1、分支语句--if-elif-else 框架: if 判断条件(test语句) then 执行的语句1; elif 判断条件(test语句) then 执行的语句2; else 执行的语句3; fi 注意: 1》每个if语句都必须加fi,同个if语句逻辑后面加一个 2》if语句的判断条件语句成立就执行,返回值为0时才执行 3》if 判断条件后面加分号 =========================================== 作业: 1、判断一个文件是否存在,如果存在的话,则终端打印文件的内容,如果不存在则输出字符串报错! 分别使用C语言与shell来完成。 实例代码1: #!/bin/bash if test -e $1 then cat $1 else echo "error!" fi 实例代码2: #!/bin/bash if [ -e $1 ] then cat $1 else echo "The file does not exist!" fi 2、执行脚本文件: 如果第一个参数是 hello, 打印hello 1, 打印hello1 实例代码: #!/bin/bash if [ $# -ne 1 ] then echo "argument error!"; exit -1 fi str=hello if [ $1 = $str ]; then echo "hello"; elif [ $1 = "1" ]; then echo "hello1"; else echo "unknow"; fi 2、分支语句--case C语言:switch switch(n) //n-->类型:整数、字符类型、枚举,绝对不可以写浮点型 { case 1: //代码块1 break; case 2: //代码块1 break; default: //代码块1 break; } shell: case case 变量 in xx) 语句1 ;; -->如果变量等于xx,就会执行语句1 yy) 语句2 ;; zz) 语句3 ;; *) 语句4 ;; esac 例子: 从键盘输入一个值,把这个值作为判断条件 如果值为1,则打印one 如果值为2,则打印two 如果值为3,则打印three 其他值,则打印error 示例代码: gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat test2.sh -n 1 #!/bin/bash 2 3 if [ $# -ne 1 ] ; 4 then 5 echo "please input two argument" 6 exit -1; 7 fi 8 9 case $1 in 10 11 hello1) echo "one";; 12 hello2) echo "two";; 13 hello33) echo "three";; 14 *) echo "error";; 15 esac 3、for循环 例子:从命令行传参,参数必须大于1;然后再把所有的参数输出; gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/02/code$ cat test2.sh #!/bin/bash if [ $# -ne 1 ] then echo "please input two argument" fi declare -i n=1 ------》表示定义一个整型变量 for word in $* ----》把字符串$*里面的单词,每次只取一个,取出来赋值到变量word里面 do echo "argv[$n]:$word" n=$n+1 done 练习:使用for循环打印1~10 示例代码1: gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/02/code$ cat test4.sh #!/bin/bash declare -i n for n in {1..10} do echo $n done 示例代码2: gec@ubuntu64:/mnt/hgfs/GZFX2021班/课堂笔记/05 shell编程/02/code$ cat test3.sh #!/bin/bash declare -i n=1 for((n=0; n<10; n++)) do echo $n done 3、while循环---》会先判断条件,再执行循环;如果条件不成立,才退出循环 while 判断条件(测试语句) do 语句; done 练习:使用while循环打印1~10 #!/bin/bash declare -i n=1 while [ $n -lt 11 ] do echo $n n=$n+1 done 4、until循环 ---》会先判断条件,再执行循环;如果条件成立,才退出循环 until 判断条件(测试语句) -->直到测试语句成立,才不执行 do 语句; done 示例代码: #!/bin/bash declare -i n=1 until [ $n -gt 10 ] --》如果n的值大于10的时候才不执行,否则会一直执行 do echo $n; n=$n+1; done C语言do-while:--》要执行一次循环,再判断条件,如果条件为真,会继续执行,否则会退出 do { }while(); 死循环: 例子: #!/bin/bash declare -i n=1 until [ $n -gt 10 ] --》如果n的值大于10的时候才不执行,否则会一直执行 do echo $n; done 十、函数--》和C语言函数是一样,都是封装某种功能,然后调用;但是传参方式和获取返回值方式不同 C语言: int func(int a, int b) { int c = a+b; printf("%d\n", c); return c; } int main() { func(10, 20); return 0; } /* $# -->运行脚本文件时的参数个数(不包括执行文件名) $* -->运行脚本文件时的传递的参数 $0 -->运行脚本文件时的执行文件名 $1 -->运行脚本文件时的传递的参数的第一个参数 $2 -->运行脚本文件时的传递的参数的第二个参数 $3 -->运行脚本文件时的传递的参数的第三个参数 $4 -->运行脚本文件时的传递的参数的第四个参数 $? -->表示最后一行命令执行结果返回值,shell命令执行成功,返回$?等于0,否则非0 */ shell:$#, $*, $0, $1, $2 //函数定义---》不会被执行 func() { echo $# declare -i n=1 for str in $* do echo "argv[$n]:$str" n=$n+1 done return 50; } func 10 20 30 --》调用函数,并传参 echo " func return value : $?" --》获取函数返回值 //执行脚本文件时,输入一个参数。写一个函数,判断是否为字符串"hello",是就返回1,否则返回0 示例代码: gec@ubuntu64:/mnt/hgfs/课堂笔记/09 shell编程/02/code$ cat test4.sh -n 1 #!/bin/bash 2 3 func() 4 { 5 if [ $1 = "hello" ] ; --》$1表示调用函数时,传递的参数 6 then 7 return 1; 8 else 9 return 0; 10 fi 11 12 13 } 14 15 16 #func hello1 17 func $1 --》$1表示执行脚本文件时命令行传递的参数 18 19 echo "return value : $?" 20 ========================== 十一、信号捕捉 trap NAME trap - trap signals SYNOPSIS trap [action condition ...] --------------------------- signal --> #include typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); C语言: void func(int sig) { printf("catch sig: %d\n", sig); } int main() { //注册信号处理函数 signal(2, func); while(1); return 0; } ------------------- shell: func() { echo "hello" } //捕捉信号--》注册信号处理函数 trap func SIGINT 死循环 until [ 2 -eq 10 ] do done ======================== shell编程: 1、项目在开发板开机启动