当前位置: 首页 > Linux

Bash笔记

时间:2023-04-06 11:56:33 Linux

body{visibility:hidden}这篇文章有多个主题:SHell代码的本质、配对符号、结束符号、退出代码和一些习惯性的并行。每个主题都是相互独立的,可以直接跳转到想看的。SHell代码的本质是Bash中的一切都是字符串。猜猜原因:Bash是为了协调Linux(或其他*nix-like系统)的进??程交互和协作而产生的,进程间通信使用的数据类型必须是字符串。例子:下面几行的意思是完全一样的:echoaecho'a'echo"a"echo\a这里,a本身就是一个普通的字符串,所以无论是使用引号消除功能还是转义功能,它仍然是一般字符。以下几行具有完全相同的含义echo'foobar'echo"foobar"echofoo''barechofoo""barechofoo\\bar以下几行具有完全相同的含义v1=foov2=ar;echo$v1\\b$v2v3=\\;echofoo"$v3"barv4='';echofoo"$v4"bar如果上面的v3和v4都只有一个空格字符串,而不是上面的两个,那么使用的时候不需要用双引号括起来,像这样:v5=\;echofoo${v5}bar大括号可以清楚地描述变量名的边界。在没有歧义的情况下,大括号可以省略。以下几行具有完全相同的含义bash-c'echofoo\\bar'bash-c"echofoo\\bar"bash-c'echofoo""bar'bash-c"echofoo''bar"v='';bash-c"echofoo'$v'bar"下面几行意思完全一样(我觉得这是可以体现“一切都是字符串”的地方)echoaae''choaa'e'choaae'ch''o'aax1=ec;${x1}hoaax2=o;ech$x2aa任何Bash代码,首先,实际上都是Bash数据。当然,它的类型是String。上面经常使用反斜杠转义空格字符。这将使它成为一个没有特殊功能的普通角色。空格符有什么特殊作用?即在解释代码时,会先将其分成多块,空格是默认的分割符号。(这个分割符也是可以改的,但是不要随便改,改了之后可能会不方便,改的方法就是改一个全局变量,这里就不说了,因为几乎没用过,也不建议这么玩,有兴趣的可以自己去看看。。。)另外,如果转义的反斜杠后面跟着一个换行符(也就是写成\n的字符)在大多数语言的代码中),它会被转义,相当于“没有这个字符”。(另外,在数据类型方面,基本数据类型是string,Bash中也有数组,但与其说是一种数据类型,不如说是一种变量的特殊函数,就像${x:-321}一样。这些数组的元素只能是字符串,不能是数组。如果数组变量没有索引,则只能包含数组第一个元素的信息,不能包含整个数组。)对,终止符,退出码,和一些习惯配对字符:":这个是跟前面或者后面最近的自己配对,没有前面的,就找后面的。":这个和上面一样。{}:这两个是一对。():这两个是一对。[]:这两个是一对。dodone:这两个是一对。iffi:这两个是一对。caseesac:这两个是一对。所有pair都有一个共同的特点:在终端SHell(也就是你手动操作的普通SHell命令行界面)上写的时候,只要有开头没有结尾,回车就不会触发执行命令的。成对字符的作用在后面描述。下面会用到一些概念:“一行命令”是指:一整块代码,你一回车就可以开始执行。给你换行,不执行,解释的时候回车也当空格处理。“行结束符”:一行代码的最后一个字符。如果是;后面跟一个换行符,可以省略,自动补全。“一条命令”是指:代表至少一个进程(其下可能有子进程,也可能没有)。“结束字符”:可以将多个命令连接成一行命令。下面的“行结束符”和“小节结束符”最显着的区别是:在前者后面输入换行符会触发新的流程执行;后者不会,只会显示一个额外的新行;当pair只有开头没有结尾时输入换行符”,但本质是不同的。结束符后面的换行符不会触发调用进程执行的原因是:在它之后和在下面命令的开头,所有的换行符对于解释器来说都相当于空格。另外,{}和()这两对可以把一行命令变成一个命令,从而进一步参与到代码的组织中process.exitcode:一般任何语句都有exitcode因为任何process都有exitcode,一般一条statement代表一个process.exitcode范围是0~255.有一个约定:0表示好的退出,rest表示各种错误退出Terminator:;:最常见的行结束符,表示前面的先执行,后面的执行完,一般可以省略,自动补全&:也是一行endingcharacter和上面的一样,但是它会让最后一行代码启动的所有进程都在后台执行,而不会阻塞当前终端的运行。|:酒吧结束。管道,把上一行标准输出的内容改成下一行标准输入的内容。管道链本身的退出代码就是最后一个的退出代码。&&:栏结束。前一个执行成功(正确退出),后一个才会执行。否则,跳过后一行并以相同的退出代码退出。||:酒吧结束。与前者正好相反,如果失败则执行前一个(错误退出),执行后一个,否则跳过后一个并以相同的退出码(即0)退出.有些习惯临时在终端命令行手动输入时,只要不是必须的,能省就省。在脚本文件中,尽可能清楚地写下所有结束字符。在脚本文件中,尽可能在所有终止符之后有换行符。对于文章的结尾,可以根据个人喜好在换行后适当缩进,以突出一些你想向代码阅读者强调的信息(代码阅读者可能还是你自己)。Playwithparallel词汇解释:Parallel:同时执行(不关心是否相互独立)Concurrency:相互独立(不关心是否同时执行)如果一般需要要同时执行,你可能会想到用&来指定进程在后台执行。或者像这样在循环体内。我有一个更好的解决方案:xargs。这是一个软件,通过安装find-utils包来安装。主要管道是|,这将直接把左边语句的标准输出当作右边语句的标准输入。如果你不知道标准输入是什么意思,你可以执行这段代码,然后尝试输入一些东西:whileread-p'::'--z;做echo$z;完毕。玩够了(按Ctrl-D退出),添加catxxx.txt|在它前面再试一次。(任何输出多行您可以阅读的文本的命令不一定要查看.txt文件。)标准输出?你在字符界面看到的大部分打印,其中一半一定是标准输出(另一半是标准错误)。标准输出和标准错误是两个名称和名称。前者是可以连接管道的接口,后者是用来输出提示信息的东西。程序有没有错并不重要。(在Linux上,文件的扩展名与文件的实际格式没有必然关系。)一般来说,管道后面的语句的程序就是处理自己的标准输入得到的内容。例如,你可以直接执行下面的代码,自己尝试输入一些东西:awk'/xx/{print$2}'——你可以单独输入这样的东西,回车试试:xxssegregeechoxxxxfgrep-vxx——--YoucanenterlikesomethingandpressEnter:xxssegregeechoxxxxbash--Youcanenterlikesomethingandpressenter:xxssegregeechoxxxx然后在当前路径中创建一个文本(名称可以是xxx),内容是:xxssegregeechoxxxx(或者你想尝试的其他内容)然后尝试这三个:catxxx|awk'/xx/{print$2}'猫xxx|fgrep-vxxcatxxx|bash,你应该能够理解什么是管道。然后,您可以通过管道将多个命令组合在一起,并将数据作为代码执行。也就是说,对于一个Linux程序来说,可能的信息来源有以下几种:参数指示。(它可以表示信息本身或获取信息的方式。)在标准输入上。(其实——和上面一样,也可以表示信息本身或者获取信息的方式。)xargs上面讲了pipeline。pipeline只是把东西丢给后面语句调用的程序,不关心其他的。不同的程序必须有不同的处理规则。xargs的规则是它会尝试把接收到的内容补全到你后面用参数指向它的程序的参数列表中。示例批量增加文件名后缀你有以下文件:assertxerzmioweeheedmox-x...你需要给它们一个共同的后缀.png你实际上需要让下面几行代码一起执行:mvassertasser.pngmvxerzxerz.pngmvmiomio.pngmvweewee.pngmvheedheed.pngmvmox-xmox-x.png...如果有10,000个文件,您不可能全部手动输入。即使您的编辑软件可以列出编辑内容,它仍然是一个大项目。使用以下代码使它们在受限条件下同时执行:ls|xargs-i-P0--mv{}{}.png这是比较完整的一种写法。其中:即{}是-i后的默认值,但-i实际上等于-i{}。-P后面的数字是并发度。0表示动态适配当前运行机器的核心数。1是普通串口,不写-P也是串口。对于稍微复杂一点的job,如果需要让xargs同时执行一个稍微复杂一点的job,比如每个job都有“失败后重启”的能力。例如:您在某个目录中有以下文件:10.21.233.1.txt10.21.179.6.txt10.33.230.5.txt...现在您需要将它们发送到服务器上的同名目录相同的文件名。一般代码为:rsync-avz--10.21.233.1.txt10.21.233.1:$PWD这是将10.21.233.1.txt发送到10.21.233.1,与本地当前目录相同的目录。如果要添加重试:retring(){retried=${1:-0};rsync-avz--10.21.233.1.txt10.21.233.1:$PWD&&{echo:succ:r::$retried;}||{echo:fail:r::$retried;execbash-c"$(declare-fretring);retring$((retried+1))";};};如上定义,然后执行retring就可以了。(还有一点,这只是个例子,rsync应该用处不大。。。如果网络出现故障,就停止它检查网络,而不是像这样努力尝试。但是,如果你批量上传图片到theInternet,网络不好,可以用这招。)如果是batch呢?retring_xrg(){重试=${1:-0};rsync-avz--{}.txt{}:$PWD&&{echo:succ:r::$retried;}||{echo:fail:r::$retried;execbash-c"$(declare-fretring_xrg);retring_xrg$((retried+1))";};}&&ls|xargs-i-P4--bash-c"$(declare-fretring_xrg);retring_xrg";就是这样!其实我还是想强调一点:codeisdatafirst。上面bash-c旁边的值是一个比较长的字符串。大家可以自己试试declare-fretring_xrg的效果。它将函数定义作为字符串发送到标准输出。如果直接执行,标准输出打印在屏幕上,如果像上面的$(declare-fretring_xrg)那样使用,抛出到标准输出的字符串将用于整体替换$(xxxx).因此,实际上,当bash-c之后的值被bash作为参数接收时,就已经是写好的函数定义了,而;retring_xrg紧跟着这个定义已经是。像$(xxx)的xxx部分,当它没有结果的时候,说明它前面的bash-c还没有解析出来——比如:还没有出生,只是准备好了。这是因为它的代码还没有完全生成。当然,有一点要明确的是,无论是--还是-c,还是bash,还是后面双引号里的那个大疙瘩,这些都是xargs的参数(或者有些人可能习惯称这个为“实参”),但我认为实际上没有必要)。其中——属于期权的概念。双破折号通常用于分隔“选项”和“一般参数”。都是软件的参数(args)(这里是xargs),但是根据软件的规则细分后(这个规则在不同的软件中一般会统一),前面的都属于“选项”(opt),后面的是“通用参数”(para)。简而言之,xargs和后面的所有内容都是一个命令。包括前面的ls|是一个单行命令。EOFbody{visibility:hidden}