快捷搜索:

详解Bash命令行处理

媒介

我看很多兄弟写脚本或敕令时呈现差错的主要缘故原由,是由于不懂得bash的敕令行处置惩罚。我在这里总结了一下,大年夜家可以参考一下。此中也涉及到双引号,单引号以及eval的技术,我会逐一讲述。

Shell从标准输入或脚本中读取的每行称为一个管道行,它包孕一个或多个由0个或多个管道字符(|)分隔的敕令。对每一个管道行,进行12个步骤的处置惩罚。

一、bash敕令处置惩罚的12个步骤;

+-------------+      单引号

|------------------------->|       |--------------------------|

| ----------------------->| 1.分隔成暗号|---- ---------------|   |

| |  ------------------->|       |   双引号    |   |

| |  |          +-------------+          |   |

| |  |             ||             |   |

| |  |读取下一个敕令      \/             |   |

| |  |   +-------------------------------------------+  |   |

| |  |   |          2.           |  |   |

| |  ------|       查验第一个暗号        |  |   |

| |     |开放的关键字          其他关键字 |  |   |

| |     |        非关键字          |  |   |

| |     +-------------------------------------------+  |   |

| |               ||             |   |

| |               \/             |   |

| |      +-----------------------------+        |   |

| | 扩展又名 |      3. 查验第一个暗号 |        |   |

| |------------| 又名            |        |   |

|        |       不是又名    |        |   |

|        +-----------------------------+        |   |

|                 ||             |   |

|                 \/             |   |

|              +--------------+         |   |

|              | 4.大年夜括号扩展 |         |   |

|              +--------------+         |   |

|                 ||             |   |

|                 \/             |   |

|              +--------------+         |   |

|              | 5.~符号扩展 |         |   |

|              +--------------+         |   |

|                 ||             |   |

|                 \/             |   |

|              +--------------+    双引号   |   |

|              | 6.参数扩展 |

结合上面的插图,这里给出敕令行的12个步骤。

1、将敕令行分成由固定元字符集分隔的暗号;

SPACE, TAB, NEWLINE, ; , (, ), , |, &

暗号类型包括单词,关键字,I/O重定向符和分号。

2、检测每个敕令的第一个暗号,查看是否为不带引号或反斜线的关键字。

假如是一个开放的关键字,如if和其他节制布局肇端字符串,function,{或(,则敕令实际上为一复合敕令。shell在内部对复合敕令进行处置惩罚,读取下一个敕令,并重复这一历程。假如关键字不是复合敕令肇端字符串(如then等一个节制布局中心呈现的关键字),则给出语法差错旌旗灯号。

3、依据又名列表反省每个敕令的第一个关键字;

假如找到响应匹配,则调换其又名定义,并退回第一步;否则进入第4步。该策略容许递归又名,还容许定义关键字又名。如alias procedure=function

4、履行大年夜括号扩展,例如a{b,c}变成ab ac

5、假如~位于单词开首,用$HOME调换~。

应用usr的主目录调换~user。

6、对任何以符号$开首的表达式履行参数(变量)调换;

7、对形式$(string)的表达式进行敕令调换;

这里是嵌套的敕令行处置惩罚。

8、谋略形式为$((string))的算术表达式;

9、把行的参数,敕令和算术调换部分再次分成单词,此次它应用$IFS中的字符做瓜分符而不是步骤1的元字符集;

10、对呈现*, ?, [ / ]对履行路径名扩展,也称为通配符扩展;

11、按敕令优先级表(跳过又名),进行敕令查寻;

12、设置完I/O重定向和其他操作后履行该敕令。

二、关于引用

1、单引号跳过了前10个步骤,不能在单引号里放单引号

2、双引号跳过了步骤1~5,步骤9~10,也便是说,只处置惩罚6~8个步骤。

这里我应用了函数递归以及eval实现了for布局。

当履行eval $@时,它经历了步骤如下:

第1步,瓜分成eval $@

第6步,扩展$@为hostname

第11步,找到内置敕令eval

重复一次敕令行处置惩罚,第11步,找到hostname敕令,履行。

留意:大概有人想当然地觉得,何必用eval呢?直接$@来履行敕令就可以了嘛。

例子2:一个范例差错的例子

差错!这里给个范例的例子大年夜家看看。

[root@home root]# a="id | cut -f1 -d' '"

[root@home root]# $a

id:无效选项 -- f

请考试测验履行‘id --help’来获取更多信息。

[root@home root]# eval $a

uid=0(root)

假如敕令行繁杂的话(包括管道或者其他字符),直接履行$a字符串的内容就会掉足。阐发如下。

$a的处置惩罚位于第6步──参数扩展,也便是说,跳过了管道阐发,于是"|", "cut", "-f1", "-d"都变成了id敕令的参数,当然就掉足啦。

但应用了eval,它把第一遍敕令行处置惩罚所得的"id", "|", "cut", "-f1", "-d"这些字符串再次进行敕令行处置惩罚,此次就能精确阐发此中的管道了。

总而言之:要包管你的敕令或脚本设计能精确经由过程敕令行处置惩罚,跳过随意率性一步,都可能造成料想外的差错!

例子3:设置系统的ls色彩显示

eval $(dircolors -b /etc/dircolors)

eval语句看护shell吸收eval参数,并再次经由过程敕令行处置惩罚的所有步骤运行它们。

它使你可以编写脚本随意创建敕令字符串,然后把它们通报给shell履行;

您可能还会对下面的文章感兴趣: