Linux应用环境实战10:Bash脚本编程语言中的美学与哲学(转)

  • 时间:
  • 浏览:7

  6.它还是一门不折不扣的动态语言哦,eval命令随便说说是太强大了,请看下图,模拟指针进行查表:

  字符串展开的流程如下:

    2.把它当成表达式;Bash中本这么表达式,后来 有了((...))和[[...]],有的是了表达式;((...))还都可以 把它后边的字符串当成算术表达式,而[[...]]会把它后边的字符串当逻辑表达式,仅此一个 特例;

    完后

  以上内容是我的胡言乱语,完后 以上内容即无法教会村里人 歌词 儿完全的Bash语法,也无法教会村里人 歌词 儿用Bash做任何许多有意义的工作。

    2. for (( expr1 ; expr2 ; expr3 )) ; do list ; done ;

    6. while list-1; do list-2; done ;

  在上图中,我展示了Bash中生成字符串的7种最好的方式:大括号展开、波浪符展开、参数展开、命令替换、算术展开、单词分割和文件路径展开。还有并有的是生成字符串的最好的方式这么讲(Process substitution和历史命令展开)。在使用Bash脚本编程的完后 ,了解以上7种字符串生成的最好的方式就够了。在交互式使用Bash命令行的完后 ,还还要了解历史命令展开,熟练使用历史命令展开还都可以 你要 事半功倍。

    4.完后 字符串不被单引号或双引号包围,则进行波浪符展开,即将~/展开为用户的主目录,将~+/展开为当前工作目录(PWD),将~-/展开为上一个 工作目录(OLDPWD);

  4.完美处置了一个 命令执行时的输出和运行状态的分离。有其它编程语言经历的人也老会 会遇到原先的大问题:当村里人 歌词 儿调用一个 函数的完后 ,函数完后 会产生一个 结果,一个 是函数的返回值,一个 是函数调用是否 成功。在C#和Java等高级语言中,往往使用try...catch等捕获异常的最好的方式来判断函数调用是否 成功,但仍然有程序运行运行员让函数返回null代表失败,而C语言许多这么异常机制的语言,随便说说是难以判断一个 函数的返回值究竟怎样才能表示该函数调用是否 成功(比如有的是就是API让函数返回-1代表失败,而有的函数运行失败是会设置errno全局变量)。在Bash中,命令运行的状态和命令的标准输出区分很明确,完后 你还要命令的标准输出,使用命令替换来生成字符串,完后 你只还要命令的运行状态,直接将命令写在if得话之中即可,完后 使用$?特殊变量来检查上根小命令的运行状态。完后 你要 在检查命令运行状态的完后 让命令的标准输出影响用户,还都可以 把它重定向到/dev/null,比如

  另外,输入输出重定向符号“>”、“<”还还都可以 和“()”共同使用,表示程序运行运行运行替换(Process substitution),如“>(list)”、“<(list)”。结合前面提到的“<”、“>”、“(list)”的含义,程序运行运行运行替换的作用是很容易猜到的哦。

  当然,自从Bash 3完后 ,Bash并有的是就提供了间接引用的功能(使用“${!var}”)。

     name () compound-command [redirection]

    1.先用元字符将一个 字符串分割为多个子串;

  前面我完后 展示了我对字符串从哪里来、到哪里去许多大问题的理解。关于字符串的去向,除了一个 表达式和一个 为变量赋值这名个 特例,剩下的就只能当命令来执行了。在前面,我提到了元字符和引用的概念,这里,还得再增加许多点定义:

  2.只使用了9个元字符、10个控制操作符和2一个 关键字,就构建了一个 完全的、面向字符串编程的语言;

    定义2:关键字(Reserved Words) 我这么将其翻译成保留字,很显然,作为编程语言来说,它们应该叫做关键字。一门编程语言肯定还要得提供选则、循环等流程控制得话,还得提供定义函数的功能。许多功能只能通过关键字实现。在Bash中,只能2一个 关键字,它们是“! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]]”。这其含晒 不少的怪怪的之处,比如“! { } [[ ]]”等符号有的是关键字,也就是 说它们当关键字使用时大约一个 单词,也就是 说它们和别的单词还要以元字符分开(后来 无法成为独立的单词)。这也是为许多在Bash中使用“! { } [[ ]]”时老会 要在它们附过留空格的是因为。(再一次证明“=”是一个 很变态的特例,完后 它既有的是元字符,有的是的是控制操作符,更加有的是关键字,它到底是许多?)

  后边的公式村里人 歌词 儿看得懂吧,我相信村里人 歌词 儿肯定看得懂。其中的[...]代表的是还都可以 有里还都可以 真这么的次要。在以上公式中,请注意第一个 公式for循环中的双括号,它执行的是其中的表达式的算术运算,这是和其它高级语言的for循环最像的,后来 很遗憾,Bash中的算术表达式目前只能计算整数。再请注意第三个公式,select语法,和for...in...循环的语法比较同类,后来 它还都可以 在屏幕上显示一个 菜单。完后 我这么记错得话,Basic语言中应该有许多功能。其它的控制特性在别的高级语言中都很常见,就不还你要 在这里啰嗦了。

  还都可以 看出,完后 有function关键字,则“()”是可选的,完后 这么function关键字,则“()”是还要的。这里还要怪怪的指出的是:函数体倘若求是compound-command,我前面总结过compound-command有并有的是形式,就是有完后 定义一个 函数并有的是会出现“{ }”哦。如下图,原先的函数也是合法的:

    8.完后 字符串不被单引号或双引号包围,则进行单词分割;

    5.完后 字符串不被单引号包围,则进行参数和变量展开;许多类的展开就是以“$”开头,这是整个Bash字符串展开中最繁杂的,其中包括用户定义的变量,包括所有的环境变量,以上并有的是展开最好的方式有的是“$”后跟变量名,还包括位置变量“$1、 $2、 ...、 $9、 ... ”,其它特殊变量:“$@、 $*、 $#、 $-、 $!、 $0、 $?、 $_ ”,甚至还有数组:“${var[i]}”, 还还都可以 在展开的过程中对字符串进行各种繁杂的操作,如:“ ${parameter:-word}、 ${parameter:=word}、 ${parameter:+word}、 ;${parameter:?word}、 ${parameter:offset}、 ${parameter:offset:length}、 ${!prefix*}、 ${!prefix@}、 ${name[@]}、 ${!name[*]}、 ${#parameter}、 ${parameter#word}、 ${parameter##word}、 ${parameter%word}、 ${parameter%%word}、 ${parameter/pattern/string}、 ${parameter^pattern}、 ${parameter^^pattern}、 ${parameter,pattern}、 ${parameter,,pattern}”;

  究竟带引号的字符串和不带引号的字符串使用起来有许多不一样呢?下图是我构建的许多比较典型的例子:

  完后 一切有的是这么特殊功能的平凡的字符串,那就无法构成一门编程语言。在Bash中,有就是符号具有特殊含义,比如“$”符号被用于字符串展开,“&”符号用于让命令在后台执行, “|”用作管道, “>” “<”用于输入输出重定向等等。就是在Bash中,随便说说同样是字符串,后来 被引号包围的字符串和不被引号包围的字符串使用起来是不一样的,被单引号包围的字符串和被双引号包围起来的字符串也是不一样的。

  下面开始英语 英语 推导Bash脚本语言的语法:

  完后 你问我Bash脚本语言哪里美?我会回答:简洁就是 美。请看下面逐条论述:

    定义1:控制操作符(Control Operator) 前面提到元字符是为了把一个 字符串分割为多个子串,而控制操作符就是 为了把一系列的字符串分割成多个命令。举例说明,在Bash中,一个 字符串 cat /etc/passwd 就是 一个 命令,第一个 单词cat是命令,第一个 单词/etc/passwd是命令的参数,而字符串 cat /etc/passwd | grep youxia 就是 一个 命令,这名个 命令分别是cat和grep,它们之间通过“|”分割,就是这里的“|”是控制操作符。熟悉Shell的村里人 歌词 肯定知道“|”代表的是管道,就是它的作用是1.把一个 字符串分割为一个 命令,2.将第一个 命令的输出作为第三个命令的输入。在Bash中,总共只能10个控制操作符,它们分别是“|| & && | ; ;; ( ) |& <newline>”。倘若看完许多控制操作符,就还都可以 认为它前面的字符串是一个 完全的命令。

  随便说说早就想写关于Bash的东西了。 村里人 歌词 儿平时喜欢对编程语言进行分类,比如面向过程的编程语言、面向对象的编程语言、函数式编程语言等等。在我心中,我认为Bash就是 一个 面向字符串的编程语言。Bash脚本语言的本质:一切皆是字符串。 Bash脚本语言的一切哲学都围绕着字符串:它们从哪里来?到哪里去?使命是许多? Bash脚本语言的一切美学都源自字符串: 由键盘上几乎所有的符号 “$ ~ ! # & ( ) [ ] { } | > < - . , ; * @ ' " ` \ ^” 排列组合而成的极富视觉冲击力的、功能极其繁杂的字符串。

  例外:

  好像忘了点许多?对了,还有输入输出重定向这么讲。输入输出重定向是Shell中又一个 发明的故事人人,它的指在有着它独特的哲学意义。许多请看下一节。

  还还都可以 将“<>”共同使用,表示打开一个 文件进行读写。

    1. for name [ [ in [ word ... ] ] ; ] do list ; done ;

  后边的4步推导是一步更进一步的,是由简单逐渐到繁杂的,最简单的命令还都可以 组合成稍繁杂的管道,再组合成更繁杂的命令序列,最后组成最繁杂的复合命令。

  下面是Bash脚本语言的流程控制得话,如下:

  完后 想用Bash干点实事,我送村里人 歌词 儿一本O'Reilly出的《Shell脚本学习指南》:Shell脚本学习指南.part1.rar Shell脚本学习指南.part2.rar Shell脚本学习指南.part3.rar Shell脚本学习指南.part4.rar (为许多一次只能上传10M啊,好好的一本书被拆分成4次要了。)

  下面图片为以上观点给出证据:

    3.完后 字符串不被单引号和双引号包围,则进行大括号展开,即将{a,b}c展开为ab ac;

  另外,我的主要参考资料来自于Bash用户手册。村里人 歌词 儿还都可以 在被委托人的系统中运行 man bash 。

  最常见的元字符就是 空格。 从后边几张图片还都可以 看出,完后 要将一个 含晒 空格的字符串赋值给一个 变量,要么把许多字符串用双引号包围,要么使用“\”对空格进行引用。 从上图中还都可以 看出,Bash中只能9个元字符,它们分别是“| & ( ) ; < > space tab”,而在其它编程语言中老会 出现的元字符“. { } [ ]”以及作为数学运算的加减乘除,在Bash中都有的是元字符。

    9.完后 字符串不被单引号或双引号包围,则进行文件路径展开;

    2.完后 字符串是用来给变量赋值,则不管它是否 被双引号包围,都认为它被双引号包围;

    7.完后 字符串不被单引号包围,则进行算术展开;算术展开的格式为$((...));

  另外一个 特殊的字符是“\”,它也是引用的并有的是。它还都可以 解除紧跟在它后边的一个 特殊字符的特殊含义(引用)。并有的是还要“\”的指在,是完后 在Bash中,许多字符称为元字符,许多字符一旦出现,就会将一个 字符串分割为多个子串。完后 还要在一个 字符串含晒 晒 许多元字符并有的是,就还要对它们进行引用。如下图:

    推导1:简单命令(Simple command) 就是 根小简单的命令,它还都可以 是一个 以上述控制操作符结尾的字符串。比如单独放上一行的 uname -r 命令(单独放上一行的命令随便说说是以<newline>结尾,<newline>是控制操作符),完后 随便说说不单独放上一行,后来 以“;”或“&”结尾,比如 uname -r; who; pwd; gvim& 其中每一个 命令有的是一个 简单命令(当然,这三个命令放上共同的这行代码不叫简单命令),“;”就是 简单地分割命令,而“&”还有让命令在后台执行的功能。这里比较特殊的是双分号“;;”,它只用在case得话中。

  最后,再来展示一下怎样才能定义函数:

     function name [()] compound-command [redirection]

  That's all。这就是 Bash脚本语言的完全语法。就这么简单。

以上一个 流程还都可以 通过下图证明:

    6.完后 字符串不被单引号包围,则进行命令替换;命令替换有并有的是格式,并有的是是$(...),并有的是是`...`;也就是 将命令的输出作为字符串的内容;

  5.使用管道和输入输出重定向让文件的读写变得简单。想一想在C语言中为什么么读文件吧,除了麻烦的open、close不说,每读一个 字符串还得先准备一个 buffer,准备长了怕浪费空间,准备短了怕缓冲区溢出,虐心啦。使用Bash,那真的是太方便了。

http://www.cnblogs.com/youxia/p/linux010.html

    推导4:复合命令(Compound Commands) 完后 将前面的简单命令、管道完后 命令序列以更繁杂的最好的方式组合在共同,就还都可以 构成复合命令。在Bash中,有4种形式的复合命令,它们分别是 (list) 、  { list; } 、  ((expression)) 、  [[ expression ]] 。请注意第2种形式和第4种形式大括号和生括号附过的空格,也请注意第2种形式中list后边的“;”,不过完后 “}”另起一行,则不还要“;”,完后 <newline>和“;”是起同样作用的。在以上4种复合命令中, (list) 是在一个 新的Shell中执行命令序列,许多命令的执行不必影响当前Shell的环境变量,而 { list; } 就是 简单地将命令序列分组。后边并有的是表达式求值前面完后 讲过,这里就不讲了。后边完后 会完全列出逻辑表达式求值的选项。

    5. if list; then list; [ elif list; then list; ] ... [ else list; ] fi ;

  在后边的图片中还都可以 看完,有许多展开最好的方式在被双引号包围的字符串中是不起作用的,比如大括号展开、波浪符展开、单词分割、文件路径展开,而只能参数展开、命令替换和算术展开是起作用的。从图片中还还都可以 看出,字符串中的参数展开、命令替换和算术展开有的是由“$”符号引导,命令替换还还都可以 由“`”引导。就是,还都可以 进一步总结为,在双引号包围的字符串中,只能“$、`、\”这名个 字符具有特殊含义。

  3.概念上具有很好的一致性;比如 (list) 复合命令的功能是执行括号内的命令序列,而“$”用于引导字符串展开,就是 $(list) 用于命令替换(就是我前面说“$()”形式的命令替换比“``”形式的命令替换更加具有一致性)。比如 ((expresion)) 用于数学表达式求值,就是 $((expression)) 代表算术展开。再比如“{}”和“,”配合使用,且后边这么空格时,代表大括号展开,后来 当还要使用“{ }”来定义复合命令时,还要把“{ }”当关键字,它们和它后边的内容还要以空格隔开,后来 “}”和它前面的根小命令之间还要三个 “;”完后 “<newline>”。许多概念上的一致性设计得非常精妙,使用起来自然而然还都可以 你要 体会到并有的是美感;

  Unix世界三个 伟大的哲学:一切皆是文件。(许多扯得怪怪的远。)Unix世界还三个 伟大的哲学:创建程序运行运行运行比较方便。(许多扯得就怪怪的远。)后来 ,每一个 程序运行运行运行一创建,就会自动打开一个 文件,它们分别是标准输入、标准输出、标准错误输出,普通状态下,它们连接到用户的控制台。在Shell中,使用数字来标识一个 打开的文件,称为文件描述符,后来 数字0、 1、 2分别代表标准输入、标准输出和标准错误输出。在Shell中,还都可以 通过“>”、“<”将命令的输入、输出进行重定向。结合exec命令,还都可以 非常方便地打开和关闭文件。还要注意的是,当文件描述符出现在“>”、“<”右边的完后 ,前面要使用“&”符号,这完后 是为了和数学表达式中的大于和小于进行区别吧。使用“&-”还都可以 关闭文件描述符。

    10.以上流程完全完成后,最后去掉 字符串外面的引号(完后 有得话)。以上流程只按以上顺序进行一遍。比如不必在变量展开后再进行大括号展开,更不必在第10步去除引用后执行前面的任何一步。完后 还要将流程再走一遍,请使用eval。

  介绍完字符串、介绍完引用和元字符,下一个 目标就是 来探讨这名个 哲学大问题:字符串从哪里来、到哪里去?通过该哲学大问题的探讨,还都可以 推导出Bash脚本语言的整个语法。字符串从哪里来?很显然,其中一个 很直接的来源就是 村里人 歌词 儿从键盘上敲上去的。除此之外,就是 我前面提到的七八九种字符串展开的最好的方式了。

    3. select name [ in word ] ; do list ; done ;

  我承认,我再一次地当了标题党。后来 不可签署,许多定是一篇精华随笔。在许多篇中,我将探讨Bash脚本语言中的美学与哲学。 这有的是一篇Bash脚本编程的教程,后来 却能你要 更加深入地了解Bash脚本编程,更加快速地学习Bash脚本编程。 阅读这篇随笔,不还要你有Bash编程的经验,但一定要和我一样热衷于探索各种编程语言的本质,感悟它们的魅力。

  探讨完了字符串从哪里来,下面来看看字符串到哪里去。也就是 为什么么使用许多字符串。使用字符串有以下几种最好的方式:

  上图是我在交互式的Bash命令行中做的许多演示。在上图中,我对变量分别赋值,不管等号右边是一个 这么引号的字符串,还是含晒 引号的字符串,甚至数字,完后 数学表达式,最终的结果,变量后边存储的有的是字符串。我使用一个 for循环显示所有的变量,还都可以 看完数学表达式也就是 以字符串的形式储存,这么被求值。

    3.给变量赋值;这也是一个 特例,怪怪的破坏Bash编程语言语法哲学的完全性。为许多这么说呢?完后 “=”即有的是一个 元字符,就是 允许两边有空格,后来 只能第一个 等号会被当成赋值运算符。

  Bash是一个 Shell,Shell出现的初衷是为了将系统中的各种工具粘合在共同,就是它最根本的功能是调用各种命令。 后来 Bash又提供了富足的编程功能。 村里人 歌词 儿老会 对编程语言进行分类,比如面向过程的语言、面向对象的语言、面向函数的语言等等。 还都可以 把Bash脚本语言看成是一个 面向字符串的语言。 Bash语言的本质就是 :一切有的是字符串。 看看下图中的许多变量:

  除了exec,输入输出重定向和read命令配合也很好用,read命令每次读取文件的一行。后来 要注意的是,输入输出重定向放上for、while等循环的循环体和循环外,效果是不一样的。如下图:

    推导3:命令序列(List) 完后 多个简单命令或多个管道放上共同,它们之间以“; & <newline> || &&”等控制操作符分开,就称之为一个 命令序列。关于“; & <newline>”前面完后 讲过了,不必重复。关于“||”和“&&”,熟悉C、C++、Java等编程语言的村里人 歌词 们歌词 肯定就是 会陌生,它们遵循同样的短路求值的思想。比如 command1 || command2 只能当command1执行不成功的完后 才执行command2,而 command1 && command2 只能当command1执行成功的完后 才执行command2。

    推导2:管道(Pipe Line) 管道是Shell中的精髓,就是 让前一个 命令的输出成为后一个 命令的输入。管道的完全语法是原先 [time [-p]] [ ! ] command1 | command2 或原先 [time [-p]] [ ! ] command1 |& command2 的。其中time关键字和!关键字有的是可选的(使用[...]指出许多次就是可选的),time关键字还都可以 计算命令运行的时间,而!关键字是将命令的返回状态取反。看清楚!关键字附过的空格哦。完后 使用“|”,就是 把第一个 命令的标准输出作为第三个命令的标准输入,完后 使用“|&”,则将第一个 命令的标准输出和标准错误输出都当成第三个命令的输入。

  请注意,数字和“>”、“<”符号之间是这么空格的。结合exec,还都可以 非常方便地使用一个 文件描述符来打开、关闭文件,如下:

    Bash语言也并有的是在所有的方面有的是完美的,还指在多少怪怪的的例外。比如前面说的“=”。除了“=”,“()”有的是一个 使用不一致的地方,那就是 对数组的初始化,比如 array=(a b c d e f) ,这和前面讲的“()”用于在子Shell中执行命令序列还真的是不一致。

  “> < & 数字 exec -”,这就是 输入输出重定向的完全。下面的公式中,我使用n代表数字,完后 是一个 不同的数字,则使用n1、n2,使用[...]代表可选参数。输入输出重定向的语法如下:

    1.把它当命令执行;这是Bash中的最根本的用法,毕竟Shell的指在就是 为了粘合各种命令。完后 一个 字符串出现在本该命令出现的地方(比如一行的开头,完后 关键字then、do等的后边),它完后 被当成命令执行,完后 它有的是个合法的命令,就会报错;

    4. case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac ;

  完后 想让任何一个 字符有的是具有特殊含义,还都可以 使用单引号将字符串包围。比如使用正则表达式的完后 ,还比如使用sed、awk等工具的完后 ,完后 sed和awk被委托人执行的命令中往往含晒 晒 就是特殊字符,就是它们的命令最好用单引号包围。 比如使用awk命令显示/etc/passwd文件中的每个用户的用户名和全名,还都可以 使用许多命令 awk -e '{print $1,$5}' ,其中,传递给awk的命令用单引号包围,说明bash不执行其中的任何替换或展开。

    7. until list-1; do list-2; done 。

  1.使用了简洁的抽象的符号。Bash脚本语言几乎使用到了键盘里有利于找到的所有符号,比如“$”用作字符串展开,“|”用作管道,“<”、“>”用作输入输出重定向,许多有的是浪费;