当前位置: 首页 > Linux

腾讯T4周末不陪对象,就为了手打这份shell编程笔记

时间:2023-04-07 00:16:35 Linux

腾讯T4周末不陪对象,就是手敲这个shell编程笔记,编程,编程应该如何分步简化呢?赵本山先生说,大象被关在冰箱里是几步,还是三步?打开冰箱,把大象放进去,然后关上冰箱。嗯,其实我们的编程就是这样的,无非就是一个输入一个输出,中间的实现过程可以按照自己的习惯来写对吧,所以文件流或者IO流其实就是这样一个概念。那么,为什么要在Linux中强调这个东西呢?如果你学过linux,那你应该知道,linux和windows的区别之一就是文件是第一位的。在linux的认知中,一切皆文件。可能你用的是图形界面的linux,可以看看。这位老师,里面的东西都是档案吗?它以文件的形式存在。重定向:(重定向不是命令)程序本身有IO0:标准输入1:标准输出2:错误输出输出重定向控制程序IO位置:本身我们的文件不是一一对应的,一一对应,一个input就是一个完整的input到一个output,然后呢,我们linux里面干嘛呢,他找了一个第三方(fd),中间人的意思,然后,我们的input连接到第三方,然后第三方相应转发数据,转发到我们希望它去的位置gocd/prof/$$/fdPs-ef查看进程ps-ef|grep13175比如大家都知道ls这个命令,你熟悉吗?反正我得到一个linux系统,就等于得到了一个数据库。它与先选择相同。我会先做一个ls,然后再做其他事情。好吧,那我们就知道了,ls只是输出显示吗?ll命令是ls-l的缩写,所以把当前目录下的内容显示到控制台,也就是我们对应显示的页面,对了,前面我们也说了012的三个属性后,对了,对应的输出就是我们的1,那我们是不是可以利用属性1来相应的改变我们的输出位置呢,好吧,我们来看看ls1>aaa里面有两点,一个是覆盖(ls/tmp1>aaa)还有一个是追加(ls/tmp1>>aaa),那我们改一下呢ls//tmp1>aaa这个命令是不是把这两个文件夹下的所有目录都进入了我的aaa,那他们的呢命令?嗯,这里分两种情况来讨论,同层(按字典序排列),和上下层(按上下层排列,也就是我们目录的深度,为什么,因为我们的linux不是目录树结构tree-Ln)结合使用newmkdiroutls//aabb1>ls01.out2>ls02.out(aabb不存在)那么这样写是不是很麻烦,能不能结合他们一起ls//aabb1>ls03.out2>ls03.out按常理是从左到右执行的吧?但是为什么这里没有我们的错误输出呢?好吧,我们来看一下ls//aabb或者ls/aabb/,我们发现无论怎么处理,最先输出的都是我们的错误日志,也就是说我的命令ls//aabb1>ls03.out2>ls03。out先把错误日志写到ls03.out,然后我们再写到标准输出的时候,就会被覆盖,ls//aabb1>>ls04.out2>>ls04.out是这样吗?还是很麻烦,人懒,又不想重写两次,怎么办?这里有一个新的符号&ls//aabb2>&11>ls05.out这里有问题,是打脸吗?我说这里可以用一个&符号,可是怎么就出问题了呢?想想这个命令,我是不是按命令来的?有2和1吗?那么2指向1,但是1指向控制台吗?也就是说,我的错误日志是不是还在控制台的Display里面,而且这个搞定之后,1又指向ls05.out了,所以这里想想,换个顺序怎么样?ls//aabb1>ls06.out2>&1这样可以吗?But,这里要注意(符号左边可以没有空格,但是右边没有问题,是可以的)ls//aabb>&ls07.out和ls//aabb>&ls07.out是两个特殊的写法,最简单的特殊写法,记住就好)在输入重定向之前,我们写输出重定向,然后我们的输入重定向读aaa<<<"helloworld"读aaa</dev/tcp/www.baidu.com/80[root@linuxStudyfd]#echo-e"GET/HTTP/1.0n"1>&8[root@linuxStudyfd]#cat0<&8注意:我们只是不是echo发了一个数据,而是我们再cat的时候他就不发消息了。为什么呢,因为我们使用的是http1.0版本,是一个只发送一次请求的短连接,如果我们要再次发送获取数据,我们需要重新定义一遍,那么我们怎么删除这么多链接呢已经创建,你可以rm-rf吗?不行,只能退出,没办法,他就是这么任性。好,我们现在要在本地定义变量:归当前shell所有,生命周期随shell而变化。假设我们定义一个变量aaa=baweiEcho$aaa,是否可以呢?显示它,但如果我重新打开一个链接,它将不起作用。如果我创建一个本地函数,同样的clearqwe没有输出值。为什么,我们不给他赋值,然后qwe=123,我给他赋值,然后我们用bawei看看有没有。部分:我们的区别在于我们可以直接从bawei获取bbb的值,但是不能通过echo$bbb直接获取我们的值位置但是如果执行Vish03.shSourcesh03.shabcdefgh就没办法了执行它。我应该怎么办?在这个地方,当出现重复的时候,我们可以把它括起来echo${12}Abc=helloEcho$abcverygood(no)======>echo${abc}verygoodawk-F':''{print$1}'passwd这里需要注意的是{}是否需要单引号,我们要传递给你bash不需要单引号,但命令需要单引号。说一个简单的例子----array[root@linuxStudysh]#msb=(1,2,3)[root@linuxStudysh]#echo$msb1,2,3[root@linuxStudysh]#echo${msb[1]}[root@linuxStudysh]#echo$msb[1]1,2,3[1]可以读取整个数组,是不是不能按下标读取?这个地方呢?这里涉及到一个东西,就是分隔符。看看我们刚才定义的数组是不是用逗号分隔的。但是在linux中,是不是空格对分隔符比较敏感呢?我们用空格试试[root@linuxStudysh]#msb=(123)[root@linuxStudysh]#echo${msb[1]}2Special$BASHPIDexecutessourcesh03.shabcdefghijklmn$*and$@不同点:·相同点:所有参数都被引用··不同点:只体现在双引号中。假设脚本运行时写了1、2、3三个参数,那么“*”就相当于“123”(传递一个参数),“@”相当于“1”“2”“3”(传递了三个参数)。注意点:pipeline[root@linuxStudysh]#a=9[root@linuxStudysh]#a=22|echogrepgrep[root@linuxStudysh]#echo$a9为什么?我们不是设置了a=22吗,怎么还是9?这是流水线的一个原理。管道是将左边命令的输出作为右边命令的输入。bash和管道在做什么?他分别在左边和右边开始狂欢。左边的bash执行完后,是否执行右边的bash?但是我们说了,这个变量的值是不是被执行了?shell的生命周期吧?在这种情况下,当bash结束时,它的生命周期是否结束?它会影响我们外面的bash吗?如果不是,那这个地方有什么用?这是我们环境变量的问题?环境我们之前用过jdk,所以知道jdk配置完成后,需要在环境变量中定义。这个地方涉及到一个问题,就是bash是如何创建的,bash是在pipeline中创建的,子bash会继承parentbash的值,但是在其他里面是不允许的。但是在其他里面,这里是不是可以看到,在pipeline里面,不管是否export,是否可以调用myvalue,因为它直接继承了parentbash的value,但是当我们写入文件的时候,如果有是没有export,没办法找到,因为它不能继承父bash,这里不能跨bash继承,比如我们创建连接后,我的bash的值就不能调用了。逻辑判断我们刚才说了一个export,好了,这里就解释一下[root@linuxStudysh]#vish05.sh[root@linuxStudysh]#chmod+xsh05.sh[root@linuxStudysh]#lsa.outpasswdsh01.shsh02.shsh04.shsh05.sh[root@linuxStudysh]#./sh05.sh.......99[root@linuxStudysh]#a=88[root@linuxStudysh]#./sh05.sh.......99[root@linuxStudysh]#exporta[root@linuxStudysh]#./sh05.sh88...99export是一个叫做非共享导出的特性,[root@linuxStudysh]#echo$a88fork():创建一个子进程,a是一个pipeline(创建子进程完全复制父进程的值,可以直接访问),一个是文件(需要导出,如果不导出,无法获取父进程的值),CopyonWrite引用和命令替换单引号:强制引用Doublequotes:弱引用,不会覆盖[root@linuxStudysh]#cp/etc/inittab/etc/passwd./cp:覆盖“./passwd”?y[root@linuxStudysh]#cp/etc/{inittab,passwd}./cp:覆盖“./inittab”?ycp:覆盖“./passwd”?y[root@linuxStudysh]#cp"/etc/{inittab,passwd}"./cp:unabletogetthefilestatus(stat)of"/etc/{inittab,passwd}":Thereisnosuchfileor目录为什么?因为如果在{}外面加上引号,它会默认把引号里的路径当作一个文件。这绝对不可能。在Bash执行之前,删除引用和反向引用。退出状态和逻辑判断退出状态就是我之前写的echo。$?逻辑判断&&(一假全假)||(onetrueandalltr??ue)Expression:Let命令:算术表达式主要使用Letc=$a+$b和C=$(($a+$b))(注:不能加$)的简化条件表达式条件表达式测试[]接下来开始编写shell脚本1、2,判断是否有参数[!$#-eq1]&&echo"参数错误!!!"&&exit23.判断用户是否存在id$1>&/dev/null&&echo"userexist"&&exit3为什么?因为有id命令,所以可以看id用户名,进行相应的检查4.#!/bin/庆典[!$#-eq1]&&echo"参数错误!!!"&&exit2id$1>&/dev/null&&echo"用户存在"&&exit3useradd$1>&/dev/null&&echo$1|passwd--stdin$1>&/dev/null&&echo"useraddsuccess"&&exit4echo"idon'tknow,useraddfail"&&exit5processcontrolIfHelpif.查看帮助文档iftest3-gt2;thenechook;fiIftest3-gt2;thenechook;elseechoerror;fiIftest3-eq4;thenechook;eliftest3-eq3;thenecho3;fiWhileWhilels/share;doechook;rm-rf/share;done有两种不同的解决方案,是普通for循环还是增强for循环?For((a=1;a<=5;a++));doecho$a;doneForiin12345;doecho$i;((i++));done在这里,添加了一个简单的seqn,也就是开一个n个数的循环