Linux Bash脚本编程语言中的美学与哲学

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

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

Linux Bash Shell入门教程 http://www.linuxidc.com/Linux/2013-08/8848.htm

一、一切皆是字符串

Bash是一个Shell,Shell出现的初衷是为了将系统中的各种工具粘合在一起,所以它最根本的功能是调用各种命令。 但是Bash又提供了丰富的编程功能。 我们经常对编程语言进行分类,比如面向过程的语言、面向对象的语言、面向函数的语言等等。 可以把Bash脚本语言看成是一个面向字符串的语言。 Bash语言的本质就是:一切都是字符串。 看看下图中的这些变量:

上图是我在交互式的Bash命令行中做的一些演示。在上图中,我对变量分别赋值,不管等号右边是一个没有引号的字符串,还是带有引号的字符串, 甚至数字,或者数学表达式,最终的结果,变量里面存储的都是字符串。我使用一个for循环显示所有的变量,可以看到数学表达式也只是以字符串的形式储存, 没有被求值。

二、引用和元字符

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

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

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

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

如果想让任何一个字符都不具有特殊含义,可以使用单引号将字符串包围。比如使用正则表达式的时候,还比如使用sed、awk等工具的时候,由于sed和 awk自己执行的命令中往往包含有很多特殊字符,所以它们的命令最好用单引号包围。 比如使用awk命令显示/etc/passwd文件中的每个用户的用户名和全名,可以使用这个命令 awk -e ‘ {print$ 1, $ 5} ‘ ,其中,传递给awk的命令用单引号包围,说明bash不执行其中的任何替换或展开。

另外一个特殊的字符是“\”,它也是引用的一种。它可以解除紧跟在它后面的一个特殊字符的特殊含义(引用)。之所以需要“\”的存在,是因 为在Bash中,有些字符称为元字符,这些字符一旦出现,就会将一个字符串分割为多个子串。如果需要在一个字符串中包含这些元字符本身,就必须对它们进行 引用。如下图:

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

三、字符串从哪里来、到哪里去

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

字符串展开的流程如下:

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

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

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

以上三个流程可以通过下图证明:

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

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

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

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

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

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

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

探讨完了字符串从哪里来,下面来看看字符串到哪里去。也就是怎么使用这些字符串。使用字符串有以下几种方式:

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

2.把它当成表达式;Bash中本没有表达式,但是有了((...))和[[...]],就有了表达式;((...))可以把它里面的字符串当成算术表达式,而[[...]]会把它里面的字符串当逻辑表达式,仅此两个特例;

3.给变量赋值;这也是一个特例,有点破坏Bash编程语言语法哲学的完整性。为什么这么说呢?因为“=”即不是一个元字符,也不允许两边有空格,而且只有第1个等号会被当成赋值运算符。

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

时间: 2024-10-09 12:52:59

Linux Bash脚本编程语言中的美学与哲学的相关文章

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

阅读目录 一.一切皆是字符串 二.引用和元字符 三.字符串从哪里来.到哪里去 四.再加上一点点的定义,就可以推导出整个Bash脚本语言的语法了 五.输入输出重定向 六.Bash脚本语言的美学:大道至简 总结: 我承认,我再一次地当了标题党.但是不可否认,这一定是一篇精华随笔.在这一篇中,我将探讨Bash脚本语言中的美学与哲学. 这不是一篇Bash脚本编程的教程,但是却能让人更加深入地了解Bash脚本编程,更加快速地学习Bash脚本编程. 阅读这篇随笔,不需要你有Bash编程的经验,但一定要和我一

Linux江湖10:Bash脚本编程语言中的美学与哲学

我承认,我再一次地当了标题党.但是不可否认,这一定是一篇精华随笔.在这一篇中,我将探讨Bash脚本语言中的美学与哲学.这不是一篇Bash脚本编程的教程,但是却能让人更加深入地了解Bash脚本编程,更加快速地学习Bash脚本编程.阅读这篇随笔,不需要你有Bash编程的经验,但一定要和我一样热衷于探索各种编程语言的本质,感悟它们的魅力. 其实早就想写关于Bash的东西了.前几天看到有博友在院子里发学习Bash的心得(这里http://www.cnblogs.com/viroyiheng/p/3988

Linux Bash脚本基本语法知识

写在前面:如果此文有幸被某位朋友看见并发现有错的地方,希望批评指正.如有不明白的地方,愿可一起探讨. 前提:读者能够基本使用一款文本编辑器以及了解文件的权限概念. 准备工作 在/home目录创建script文件用于保存所有的脚本程序: # mkdir /home/script # cd /home/script/ Bash脚本的基本输入输出 第一个bash脚本: # vim ./hello-world.sh 说明: "#!"是一个约定标记,它告诉系统这个脚本需要什么解释器来执行 作为可

linux Bash脚本基础符号总结 (一)

1.初识Bash 首先编译一个简单的bash vim hello.sh 使用vim编辑hello.sh ,输入如下代码并保存: #!/bin/bash echo hello word 运行Bash脚本的方式: # 使用shell来执行 $ sh hello.sh # 使用bash来执行 $ bash hello.sh 还可以让脚本本身就具有可执行权限,通过chmod命令可以修改: # 赋予脚本的所有者该执行权限,允许该用户执行该脚本 $ chmod u+x hello.sh # 执行命令,这将使

Linux Bash 脚本:自定义延迟代码块(裸数据保存方案)

结合 alias 和 read 用法,可以保存一些将要延迟运行的脚本,或者裸数据(字符串不被扩展)到一个变量中,以备后用. $ alias BEGIN='read -d "" $1 <<"END"' $ BEGIN block1 > ls -la > END $ eval $block1 total 10 drwxr-xr-x 1 Xiaoqian Administ 4096 Nov 5 22:42 ./ drwxr-xr-x 12 Xiao

Linux Bash 脚本:自己定义延迟代码块(裸数据保存方案)

结合 alias 和 read 使用方法.能够保存一些将要延迟执行的脚本,或者裸数据(字符串不被扩展)到一个变量中.以备后用. $ alias BEGIN='read -d "" $1 <<"END"' $ BEGIN block1 > ls -la > END $ eval $block1 total 10 drwxr-xr-x 1 Xiaoqian Administ 4096 Nov 5 22:42 ./ drwxr-xr-x 12 Xi

bash脚本编程之if分支结构和位置变量的应用以及交互示例

bash脚本编程的结构: (bash脚本编程语言是脚本类语言.解释型语言.过程式编程语言.) 过程式编程语言的结构: 顺序执行结构(默认): 从上到下,自左而右的执行所有的语句(命令) 选择执行结构: 当条件满足或不满足时,才会执行对于的语句(命令) 循环执行结构: 重复执行某段语句(命令) 在bash脚本编程语言中也具备上述结构: 顺序执行结构:bash默认的执行结构 选择执行结构: 根据给定的条件的逻辑判断结果或根据某个可选取的取值范围进而选择某个分支结构中的语句(命令)予以执行: if:分

用于监视Linux上的内存使用情况的Bash脚本

用于监视Linux上的内存使用情况的Bash脚本 2019-06-17 11:32:45作者:戴进稿源:云网牛站 在本文中,我们添加了两个shell脚本来监视Linux操作系统上的内存利用率,即用于监视Linux上的内存使用情况的Bash脚本,当系统达到给定阈值时,它将触发并发送电子邮件给你.可以参考脚本在实践中的应用:用脚本的方法解决搜狗拼音占用大量内存的问题. 方法一.Linux Bash脚本监视内存利用率并发送电子邮件 如果只想在系统达到给定阈值时通过邮件获取当前内存利用率百分比,请使用以

bash脚本编程基础

bash编程   bash脚本编程是过程式解释编程,其实就是linux命令的堆砌,既然是编程就应该有相应编程语法.    与任何过程式编程一样,过程式编程的特点就是:顺序执行,选择执行,循环执行.    过程式编程:以指令为中心,设计算法,数据服务于算法,过程式编程的灵魂:算法.    1.变量:数值变量,字符变量           bash环境:                本地变量:当前shell进程:                环境变量:当前shell进程及其子进程: