[
    {
        "type": "text",
        "text": "什么是 Shell？",
        "text_level": 1,
        "bbox": [
            144,
            133,
            317,
            155
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "是一种程序设计语言。",
        "bbox": [
            144,
            199,
            317,
            215
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "Shell 是指一种应用程序，这个应用程序提供了一个界面，用户通过这个界面访问操作系统内核的服务。",
        "bbox": [
            144,
            218,
            847,
            252
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "Bash（GNU Bourne-Again Shell）是一个为 GNU 计划编写的 Unix shell，它是许多Linux 平台默认使用的 shell。",
        "bbox": [
            144,
            255,
            847,
            288
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "shell 是一个命令解释器，是介于操作系统内核与用户之间的一个接口层。它也是一种能力很强的计算机语言，被称为解释性语言或脚本语言 script。可以通过将系统调用、公共程序、工具和编译过的二进制程序“粘合”在一起来建立应用，这是大多数脚本语言的共同特征，所以脚本语言又被称为“胶水语言”。",
        "bbox": [
            144,
            292,
            847,
            363
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "Shell是系统的用户界面，提供了用户与内核进行交互操作的一种接口(命令解释器) 。它接收用户输入的命令并把它送入内核去执行。起着协调用户与系统的一致性和在用户与系统之 间 进 行 交 互 的 作 用 。",
        "bbox": [
            144,
            366,
            848,
            420
        ],
        "page_idx": 0
    },
    {
        "type": "image",
        "img_path": "images/2f1fbe30e5df1933f987b31f395caca2a97bb40a4f308e9039adf97eb01bcfc5.jpg",
        "image_caption": [],
        "image_footnote": [],
        "bbox": [
            147,
            423,
            631,
            596
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "Python、PHP、Perl、javascript 等都是脚本语言，解释执行，有相似的基本特征。",
        "bbox": [
            144,
            607,
            789,
            623
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "事实上，所有的 UNIX 命令和工具再加上公共程序，对于 shell 脚本来说，都是可调用的。",
        "bbox": [
            144,
            626,
            853,
            640
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "Shell 脚本对于实现管理系统任务的自动化和执行其它重复性工作来说，非常适合，灵活强大，比编写编译型程序更加高效灵活。",
        "bbox": [
            144,
            644,
            848,
            678
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "内 置 命 令 ： 出 于 效 率 的 考 虑 ， 将 一 些 常 用 命 令 的 解 释 程 序 构 造 在 Shell 内 部外 置 命 令 ： 存 放 在 /bin 、 /sbin 目 录 下 的 命 令实用程序：存放在/usr/bin、/usr/sbin、/usr/share、/usr/local/bin 等目录下的实用程序用 户 程 序 ： 用 户 程 序 经 过 编 译 生 成 可 执 行 文 件 后 ， 可 作 为 Shell 命 令 运 行Shell 脚 本 ： 由 Shell 语 言 编 写 的 批 处 理 文 件 ， 可 作 为 Shell 命 令 运 行",
        "bbox": [
            144,
            681,
            848,
            772
        ],
        "page_idx": 0
    },
    {
        "type": "text",
        "text": "内部命令、应用程序、shell脚本",
        "bbox": [
            144,
            793,
            406,
            808
        ],
        "page_idx": 0
    },
    {
        "type": "table",
        "img_path": "images/fbf3225e75a711ea24ea1be2969ee839f31ba26037a31c311c221be798fc41e1.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>命\n命\n通</td><td>令\n令\n配</td><td>行\n种\n符</td><td>解\n执行\n顺序</td><td>释\nwild-card</td><td>characters</td><td>历史</td><td>I/O</td></tr></table>",
        "bbox": [
            144,
            810,
            848,
            901
        ],
        "page_idx": 0
    },
    {
        "type": "table",
        "img_path": "images/90a01365fbbf634e2472f01e6aa8771cadf377f4ff2e67d1415d7eefe32607fc.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>管</td><td>道</td><td>pipes</td><td>(</td></tr><tr><td>命</td><td>令 替 换</td><td>或 $(</td><td>或 $()</td></tr><tr><td>Shell</td><td>编 程 语 言</td><td>Shell</td><td>Script</td></tr></table>",
        "bbox": [
            146,
            91,
            840,
            147
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "都有哪些 shell？",
        "bbox": [
            147,
            167,
            273,
            183
        ],
        "page_idx": 1
    },
    {
        "type": "table",
        "img_path": "images/1a6197dc2e70844015da3351b232066b3b4325449fe1854f6b0463c3e4ea69c4.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>Bash (Bourne Again Shell)</td><td>bash是大多数Linux系统的默认Shell。 bash与bash完全向后兼容,并且在bash的基础上增加和增 强了很多特性。 bash也包含了很多C Shell和Korn Shell中的优点。 bash有很灵活和强大的编程接口,同时又有很友好的用 户界面</td></tr><tr><td>Ksh (Korn Shell)</td><td>Korn Shell(ksh)由Dave Korn所写。它是UNIX系统上的 标准Shell。 在Linux环境下有一个专门为Linux系统编写的Korn Shell的 扩展版本,即Public Domain Korn Shell(pdksh)。</td></tr><tr><td>tcsh (csh 的扩展)</td><td>tcsh是C Shell的扩展。tcsh与csh完全向后兼容,但它包 含了更多的使用户感觉方便的新特性,其最大的提高是在 命令行编辑和历史浏览方面</td></tr></table>",
        "bbox": [
            147,
            200,
            566,
            361
        ],
        "page_idx": 1
    },
    {
        "type": "table",
        "img_path": "images/01f9555c37c1dbe9c10a9916879a391417f600c77eb93dc5a41135d92258e070.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>(</td><td>sh</td><td>、</td><td>bash</td><td>、</td><td>ksh</td><td>、</td><td>csh</td><td>等</td><td>)</td></tr><tr><td>登</td><td></td><td>录</td><td></td><td>login</td><td></td><td>:</td><td></td><td>stu01</td><td></td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td>password</td><td>:</td><td>student01</td><td></td></tr><tr><td></td><td></td><td></td><td>注意</td><td>:</td><td>case</td><td colspan=\"3\">sensitive(上限case/lowercase)</td><td></td></tr><tr><td>提</td><td>示</td><td>符</td><td></td><td></td><td></td><td>#</td><td>、</td><td>$</td><td></td></tr><tr><td>注</td><td></td><td>销</td><td></td><td></td><td></td><td colspan=\"3\">exit/login/Ctrl+D</td><td></td></tr><tr><td>重</td><td></td><td>启</td><td></td><td>动</td><td></td><td colspan=\"3\">reboot</td><td></td></tr></table>",
        "bbox": [
            146,
            369,
            853,
            499
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "关闭系统 poweroff ",
        "bbox": [
            147,
            501,
            300,
            517
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "查看系统中目前可以使用的shells",
        "bbox": [
            147,
            556,
            413,
            571
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "Cat /etc/shells ",
        "bbox": [
            147,
            575,
            268,
            589
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "切换到sh模式",
        "bbox": [
            147,
            593,
            265,
            609
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "Sh ",
        "bbox": [
            147,
            612,
            173,
            626
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "推出sh模式",
        "bbox": [
            147,
            630,
            248,
            645
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "exit ",
        "bbox": [
            147,
            650,
            181,
            662
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "学习一门语言习惯与先写一个HelloWorld的程序，这里就写一个HelloWorld的脚本。下面启动 vim 编辑 hello.sh 脚本文件。后缀名“.sh”不是必须的，但是更容易表示这是一个脚本程序文件。",
        "bbox": [
            146,
            667,
            848,
            720
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "vim hello.sh ",
        "bbox": [
            147,
            741,
            250,
            756
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "#!/bin/bash ",
        "bbox": [
            147,
            774,
            247,
            789
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "# This is a comment ",
        "bbox": [
            147,
            807,
            317,
            821
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "echo Hello World ",
        "bbox": [
            147,
            840,
            292,
            854
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "上述例子包含三行，以下逐行解释。",
        "bbox": [
            147,
            872,
            423,
            889
        ],
        "page_idx": 1
    },
    {
        "type": "text",
        "text": "第一行以“#!”开头，说明脚本的解释器的路径位置信息。Linux 系统根据#! 及该字符串后面的信息确定使用哪个解释器对该脚本进行解释执行。",
        "bbox": [
            144,
            93,
            848,
            129
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "上述例子中的 /bin/bash 就表明该文件是一个 BASH 程序，需要由 /bin 目录下的 bash 解析器来解释执行。BASH 一般是存放在 /bin 目录下，但是在有的发行版中，bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或 /usr/local/sbin 这样的目录下，所以在“#!”之后要正确写出解释器路径位置；可以使用 locate、find、which 或whereis等命令找出确定bash的具体路径位置。也可以查看/etc/shells文件内容，确定bash 路径。",
        "bbox": [
            144,
            143,
            853,
            254
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "另外要说明的是，该行要顶行顶格，前面不要有空行和空格。",
        "bbox": [
            146,
            269,
            621,
            287
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "第二行以“#”字符开头，表示其后的内容是注释，不需要解释执行。这些注释语句是在脚本中做一些注释或标记，让脚本更具可读性。",
        "bbox": [
            144,
            302,
            843,
            338
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "第三行的echo 语句的功能是把echo 后面的字符串打印到标准输出stdout。由于echo 后跟的是 \"Hello World\" 字符串，因此执行 echo 命令的结果是在终端上输出了 \"HelloWorld\"这个字符串。Bash脚本每行一条命令，无需“;”结束。",
        "bbox": [
            144,
            354,
            850,
            407
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "命令解释过程",
        "text_level": 1,
        "bbox": [
            146,
            424,
            260,
            441
        ],
        "page_idx": 2
    },
    {
        "type": "image",
        "img_path": "images/f0a7db17bad874101f01a82179061db465446ebe08a2ff895797836057ad4ded.jpg",
        "image_caption": [],
        "image_footnote": [],
        "bbox": [
            154,
            461,
            331,
            583
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "当命令不在命令行中执行，而是从一个文件中执行时，该文件就称为 Shell 脚本。",
        "bbox": [
            144,
            600,
            771,
            617
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "Shell 脚本是纯文本文件。",
        "bbox": [
            146,
            619,
            347,
            634
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "Shell 脚本通常以 .sh 作为后缀名，但不是必须。",
        "bbox": [
            144,
            638,
            519,
            653
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "Shell 脚本是以行为单位的，在执行脚本的时候会分解成一行一行依次执行。",
        "bbox": [
            144,
            656,
            732,
            671
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "Shell 是一种功能强大的解释型编程语言",
        "bbox": [
            144,
            675,
            463,
            690
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "通常用于完成特定的、较复杂的系统管理任务",
        "bbox": [
            144,
            693,
            504,
            709
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "Shell 脚本语言非常擅长处理文本类型的数据",
        "bbox": [
            144,
            712,
            497,
            728
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "shell 脚本的成分",
        "bbox": [
            146,
            730,
            282,
            746
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "程序元素",
        "bbox": [
            144,
            763,
            223,
            778
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "保留字、运算符、表达式",
        "bbox": [
            144,
            782,
            347,
            797
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "变量、数组、输入输出",
        "bbox": [
            146,
            800,
            327,
            815
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "控制结构（顺序、分支、循环、子程序调用）",
        "bbox": [
            144,
            818,
            494,
            835
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "Shell 功能",
        "bbox": [
            146,
            838,
            231,
            853
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "执行命令（内置命令、外部命令、自编程序）",
        "bbox": [
            144,
            870,
            494,
            885
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "重定向、管道、命令替换、命令聚合",
        "bbox": [
            146,
            889,
            433,
            904
        ],
        "page_idx": 2
    },
    {
        "type": "text",
        "text": "通配符、注释符、……",
        "bbox": [
            146,
            93,
            327,
            108
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "Shell 脚本的建立",
        "bbox": [
            147,
            112,
            282,
            126
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "使用文本编辑器编辑脚本文件",
        "bbox": [
            147,
            130,
            381,
            145
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ vi script-file ",
        "bbox": [
            147,
            149,
            260,
            162
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "为脚本文件添加可执行权限",
        "bbox": [
            147,
            167,
            363,
            181
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ chmod $+ { \\sf x }$ script-file ",
        "bbox": [
            147,
            186,
            329,
            200
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "Shell 脚本的执行",
        "bbox": [
            147,
            204,
            282,
            218
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "在子 Shell 中执行",
        "bbox": [
            147,
            223,
            285,
            237
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ bash script-file ",
        "bbox": [
            147,
            242,
            287,
            256
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ script-file ",
        "bbox": [
            147,
            261,
            242,
            275
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "在当前Shell中执行",
        "bbox": [
            147,
            279,
            302,
            293
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ source script-file ",
        "bbox": [
            147,
            297,
            302,
            312
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ . script-file ",
        "bbox": [
            147,
            316,
            257,
            331
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "PATH 环境变量的默认值不包含当前目录，",
        "bbox": [
            147,
            334,
            468,
            349
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "若脚本文件在当前目录，应使用 ./script-file",
        "bbox": [
            147,
            353,
            490,
            368
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "PATH 环境变量的默认值包含 ~/bin 目录，",
        "bbox": [
            147,
            370,
            468,
            386
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "用户可以将自己的脚本文件存放在 ~/bin 目录，",
        "bbox": [
            147,
            390,
            509,
            405
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "之后即可直接调用脚本文件名执行脚本了",
        "bbox": [
            147,
            407,
            467,
            423
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "shell脚本的编码与规范",
        "bbox": [
            147,
            426,
            334,
            442
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "以 #! 开头：通知系统用何解释器执行此脚本",
        "bbox": [
            147,
            458,
            494,
            474
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "#!/bin/bash ",
        "bbox": [
            147,
            478,
            245,
            492
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "#!/bin/ksh ",
        "bbox": [
            147,
            497,
            235,
            511
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "以注释形式说明如下的内容：",
        "bbox": [
            147,
            514,
            369,
            530
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "# 脚本名称",
        "bbox": [
            147,
            533,
            238,
            549
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "# 脚本功能",
        "bbox": [
            147,
            552,
            238,
            567
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "# 作者及联系方式",
        "bbox": [
            147,
            571,
            290,
            586
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "# 版本更新记录",
        "bbox": [
            147,
            590,
            273,
            605
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "# 版权声明",
        "bbox": [
            147,
            608,
            238,
            623
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "# 对算法做简要说明（如果是复杂脚本）",
        "bbox": [
            147,
            626,
            455,
            640
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "脚本调试",
        "bbox": [
            147,
            659,
            221,
            674
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "在 bash 调用脚本时使用参数",
        "bbox": [
            147,
            678,
            376,
            692
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "$\\$ 1$ bash [-x] [-n] [-v] scriptName ",
        "bbox": [
            147,
            696,
            405,
            712
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "在脚本中使用 bash 内置的 set 命令使整个或部分脚本处于调试模式",
        "bbox": [
            147,
            715,
            673,
            730
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "开启：set [-x] [-n] [-v] ",
        "bbox": [
            147,
            734,
            324,
            749
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "结束：set $[ + \\mathsf { x } ] [ + \\mathsf { n } ] [ + \\mathsf { v } ]$ ",
        "bbox": [
            147,
            753,
            336,
            768
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "sh $- { \\sf x }$ 脚本名",
        "bbox": [
            147,
            771,
            250,
            785
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "该选项可以使用户跟踪脚本的执行，此时shell 对脚本中每条命令的处理过程为：先执行替换，然后显示，再执行它。",
        "bbox": [
            147,
            789,
            833,
            822
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "shell 显示脚本中的行时，会在行首添加一个加号 “ + ”。",
        "bbox": [
            147,
            826,
            583,
            841
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "sh –v 脚本名",
        "bbox": [
            147,
            845,
            250,
            859
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "在执行脚本之前，按输入的原样打印脚本中的各行",
        "bbox": [
            147,
            863,
            539,
            878
        ],
        "page_idx": 3
    },
    {
        "type": "text",
        "text": "sh –n 脚本名",
        "bbox": [
            144,
            93,
            253,
            108
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "对脚本进行语法检查，但不执行脚本。如果存在语法错误，shell 会报错，如果没有错误，则不显示任何内容。",
        "bbox": [
            144,
            111,
            836,
            145
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set 命令",
        "bbox": [
            146,
            149,
            215,
            162
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "在脚本内使用 set 命令开启调试选项",
        "bbox": [
            144,
            181,
            433,
            197
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set -x ：显示由shell执行的命令及其参数",
        "bbox": [
            144,
            200,
            475,
            215
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set -v ：显示由 shell 读入的命令行",
        "bbox": [
            146,
            219,
            423,
            234
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set -n ：读取命令但不执行他们，用于语法检查",
        "bbox": [
            144,
            237,
            519,
            253
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "在脚本内使用set命令关闭已开启的调试选项",
        "bbox": [
            144,
            255,
            500,
            271
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set $+ \\mathsf { x }$ ",
        "bbox": [
            146,
            275,
            201,
            288
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set $+ \\nu$ ",
        "bbox": [
            146,
            294,
            201,
            307
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "set $+ \\mathsf { n }$ ",
        "bbox": [
            146,
            313,
            201,
            325
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "shell脚本的类型",
        "bbox": [
            146,
            330,
            280,
            344
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "非交互式脚本",
        "bbox": [
            146,
            363,
            257,
            378
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "不需要读取用户的输入, 也不用向用户反馈某些信息",
        "bbox": [
            146,
            381,
            549,
            395
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "每次执行都是可预见的, 因为它不读取用户输入, 参数是固定的",
        "bbox": [
            146,
            400,
            628,
            414
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "可以在后台执行",
        "bbox": [
            146,
            419,
            275,
            434
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "交互式脚本",
        "bbox": [
            147,
            437,
            240,
            451
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "脚本可以读取用户的输入, 实时向用户反馈信息（输出某些信息）",
        "bbox": [
            146,
            455,
            643,
            470
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "这样的脚本更灵活, 每次执行时的参数可由用户动态设定",
        "bbox": [
            146,
            473,
            584,
            488
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "用户界面更友好，但不适用于自动化任务（如 cron 任务）",
        "bbox": [
            146,
            492,
            589,
            508
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "掌握一种文本编辑器的使用（Vi）",
        "bbox": [
            146,
            511,
            401,
            526
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "熟悉 Linux 文件系统的布局",
        "bbox": [
            146,
            529,
            363,
            545
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "学习 Shell 的各种功能",
        "bbox": [
            147,
            548,
            322,
            563
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "重定向、管道、命令替换、命令聚合",
        "bbox": [
            146,
            565,
            433,
            582
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "学习各种管理和监视命令的使用",
        "bbox": [
            147,
            585,
            398,
            600
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "用户管理、权限管理、进程管理、包管理……",
        "bbox": [
            146,
            602,
            502,
            619
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "系统监视、网络监视……",
        "bbox": [
            147,
            621,
            349,
            637
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "学习各种文本文件工具的使用",
        "bbox": [
            146,
            640,
            381,
            656
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "cat、grep、tr、sed、awk …… ",
        "bbox": [
            146,
            659,
            393,
            675
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "正则表达式",
        "bbox": [
            147,
            678,
            240,
            692
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "Shell 环境",
        "bbox": [
            146,
            728,
            230,
            744
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "运行脚本有多种方法：",
        "bbox": [
            146,
            780,
            317,
            795
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "# 使用 shell 来执行",
        "bbox": [
            146,
            813,
            300,
            829
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "sh hello.sh ",
        "bbox": [
            147,
            846,
            240,
            860
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "# 使用 bash 来执行",
        "bbox": [
            146,
            878,
            302,
            894
        ],
        "page_idx": 4
    },
    {
        "type": "text",
        "text": "bash hello.sh ",
        "bbox": [
            144,
            93,
            263,
            107
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "# 还可以赋予脚本所有者执行权限，允许该用户执行该脚本",
        "bbox": [
            144,
            126,
            608,
            141
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "chmod $\\uplus \\dag \\boldsymbol { \\mathsf { r } } \\boldsymbol { \\mathsf { X } }$ hello.sh ",
        "bbox": [
            144,
            159,
            319,
            173
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "./hello.sh ",
        "bbox": [
            146,
            192,
            226,
            205
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "# 使用.命令来执行，不创建子进程",
        "bbox": [
            144,
            224,
            418,
            239
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": ". ./hello.sh ",
        "bbox": [
            146,
            256,
            236,
            271
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "# 使用 source 来执行，与.命令等价",
        "bbox": [
            144,
            290,
            428,
            305
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "source hello.sh ",
        "bbox": [
            144,
            323,
            275,
            336
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "1. ./hello.sh 报错 zsh: 权限不够 ",
        "text_level": 1,
        "bbox": [
            146,
            356,
            406,
            370
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "当你直接运行 ./hello.sh 时，系统会尝试把 hello.sh 当作一个可执行程序运行，但要求：",
        "bbox": [
            144,
            388,
            836,
            404
        ],
        "page_idx": 5
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " 文件必须具有可执行权限（ $\\mathbf { x }$ 权限）。",
            " 如果文件没有 $\\pmb { \\times }$ 权限，就会报 权限不够（Permission denied）。"
        ],
        "bbox": [
            174,
            420,
            712,
            469
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "Chomod ",
        "bbox": [
            206,
            487,
            282,
            500
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "2. . ./hello.sh 能正常运行",
        "text_level": 1,
        "bbox": [
            144,
            519,
            354,
            535
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "当你使用 . ./hello.sh（或等价的 source ./hello.sh）时，Shell 会直接在当前 Shell 进程中执行脚本内容，而不是启动一个新的子 Shell。",
        "bbox": [
            144,
            552,
            843,
            586
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "这种方式的特点是：",
        "bbox": [
            144,
            589,
            299,
            605
        ],
        "page_idx": 5
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " 不需要文件有可执行权限（因为 Shell 直接读取文件内容并执行）。",
            " 脚本中的变量、函数等会影响当前 Shell 环境（而./hello.sh 不会）。"
        ],
        "bbox": [
            174,
            621,
            746,
            671
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "为什么它能工作？",
        "text_level": 1,
        "bbox": [
            144,
            687,
            284,
            703
        ],
        "page_idx": 5
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " .（或source）是 Shell 的内置命令，不依赖文件权限。",
            " 它直接读取文件内容并逐行执行，因此即使没有 $\\pmb { \\times }$ 权限也能运行。"
        ],
        "bbox": [
            174,
            720,
            712,
            769
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "如果想要保存脚本的输出 hello world 为一个文本，那么该怎么办呢？",
        "bbox": [
            144,
            785,
            685,
            802
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "#!/bin/bash ",
        "bbox": [
            149,
            819,
            252,
            833
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "echo \"hello world\" $>$ my.out ",
        "bbox": [
            149,
            852,
            384,
            866
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "用 cat 命令查看 my.out 文件的内容。",
        "bbox": [
            144,
            885,
            431,
            901
        ],
        "page_idx": 5
    },
    {
        "type": "text",
        "text": "cat my.out ",
        "bbox": [
            146,
            93,
            238,
            109
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "关键区别总结 ",
        "text_level": 1,
        "bbox": [
            147,
            124,
            258,
            142
        ],
        "page_idx": 6
    },
    {
        "type": "table",
        "img_path": "images/82e09f7779ae175bc41788ca22d146bba6f34332ff45be35788c0afb983e9401.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>方式</td><td>是否需要x权限</td><td>执行环境</td><td>典型用途</td></tr><tr><td>./hello.sh</td><td>需要</td><td>新的子Shell</td><td>运行独立脚本</td></tr><tr><td>../hello.sh</td><td>不需要</td><td>当前Shell</td><td>加载环境变量或函数到当前会话</td></tr><tr><td>bashhello.sh</td><td>不需要</td><td>新的子Shell</td><td>直接指定解释器执行脚本</td></tr></table>",
        "bbox": [
            144,
            166,
            808,
            404
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "正则表达式",
        "text_level": 1,
        "bbox": [
            147,
            419,
            240,
            435
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "正则表达式是使用某种模式（pattern）去匹配（matching）一类字符串的一个公式。",
        "bbox": [
            144,
            451,
            840,
            468
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "通 常 使 用 正 则 表 达 式 进 行 查 找 、 替 换 等 操 作 。",
        "bbox": [
            146,
            469,
            838,
            487
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "在 适 当 的 情 况 下 使 用 正 则 表 达 式 可 以 极 大 地 提 高 工 作 效 率 。",
        "bbox": [
            147,
            488,
            838,
            505
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "有 两 种 风 格 的 正 则 表 达 式 ：",
        "bbox": [
            147,
            507,
            796,
            523
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "POSIX 风 格 的 正 则 表 达 式",
        "bbox": [
            147,
            525,
            848,
            541
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "Perl 风 格 的 正 则 表 达 式 （ Perl-compatible regular expression ）",
        "bbox": [
            147,
            543,
            838,
            561
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "基 本 的 正 则 表 达 式 Basic regular expression (BRE)",
        "bbox": [
            147,
            562,
            848,
            580
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "grep 按 模 式 匹 配 文 本",
        "bbox": [
            147,
            581,
            848,
            598
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "ed 个 原 始 的 行 编 辑 器",
        "bbox": [
            147,
            599,
            848,
            615
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "sed 个 流 编 辑 器",
        "bbox": [
            147,
            618,
            848,
            634
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "vim 个 屏 幕 编 辑 器",
        "bbox": [
            147,
            636,
            848,
            653
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "emacs 个 屏 幕 编 辑 器",
        "bbox": [
            147,
            655,
            848,
            671
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "扩 展 的 正 则 表 达 式 Extended regular expression (ERE)",
        "bbox": [
            147,
            673,
            848,
            690
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "egrep 按 模 式 匹 配 文 本",
        "bbox": [
            147,
            692,
            848,
            709
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "awk 进 行 简 单 的 文 本 处 理",
        "bbox": [
            147,
            709,
            848,
            728
        ],
        "page_idx": 6
    },
    {
        "type": "text",
        "text": "在 Shell 中有一些具有特殊的意义字符，称为 Shell 元字符（shell metacharacters）。若不以特殊方式（使用转义字符）指明，Shell 并不会把它们当做普通文字符使用。",
        "bbox": [
            144,
            762,
            838,
            797
        ],
        "page_idx": 6
    },
    {
        "type": "table",
        "img_path": "images/383bd1d08ac43e5ebf36da8ca2ec4a658f2b26d0f1b3538235c29a7547a9479d.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>字符</td><td>含义</td><td>字符</td><td>含义</td></tr><tr><td>'</td><td>强引用</td><td>*、?、!</td><td>通配符</td></tr><tr><td>\"</td><td>弱引用</td><td>&lt;、&gt;、&gt;&gt;</td><td>重定向</td></tr><tr><td>\\</td><td>转义字符</td><td>-</td><td>选项标</td></tr><tr><td>$</td><td>变量引用</td><td>#</td><td>注释符</td></tr><tr><td>;</td><td>命令分离符</td><td>空格、换行符</td><td>命令分</td></tr></table>",
        "bbox": [
            147,
            815,
            1000,
            903
        ],
        "page_idx": 6
    },
    {
        "type": "table",
        "img_path": "",
        "table_caption": [],
        "table_footnote": [],
        "bbox": [
            147,
            90,
            1000,
            262
        ],
        "page_idx": 7
    },
    {
        "type": "table",
        "img_path": "images/40e96966f78386d62aa3bfc0502b229d2c9039a9cb83b951152d92d318aed4f4.jpg",
        "table_caption": [
            "通配符（元字符）"
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>元字符</td><td colspan=\"3\">含义</td><td>类型</td><td>举例</td><td colspan=\"2\">说明</td></tr><tr><td>^</td><td colspan=\"3\">匹配首字符</td><td>BRE</td><td>^x</td><td colspan=\"2\">以字符x开</td></tr><tr><td>$</td><td colspan=\"3\">匹配尾字符</td><td>BRE</td><td>x$</td><td colspan=\"2\">以x字符结</td></tr><tr><td>.</td><td colspan=\"3\">匹配任意一个字符</td><td>BRE</td><td>l..e</td><td colspan=\"2\">love, life, l</td></tr><tr><td>?</td><td colspan=\"3\">匹配任意一个可选字符</td><td>ERE</td><td>xy?</td><td colspan=\"2\">x, xy</td></tr><tr><td>*</td><td colspan=\"3\">匹配零次或多次重复</td><td>BRE</td><td>xy*</td><td colspan=\"2\">x, xy, xyy, x</td></tr><tr><td>+</td><td colspan=\"3\">匹配一次或多次重复</td><td>ERE</td><td>xy+</td><td colspan=\"2\">xy, xyy, xyy</td></tr><tr><td>[...]</td><td colspan=\"3\">匹配任意一个字符</td><td>BRE</td><td>[xyz]</td><td colspan=\"2\">x, y, z</td></tr><tr><td>()</td><td colspan=\"3\">对正则表达式分组</td><td>ERE</td><td>(xy)+</td><td colspan=\"2\">xy, xyxy, x</td></tr><tr><td colspan=\"2\">元字符</td><td>含义</td><td>类型</td><td colspan=\"2\">举例</td><td colspan=\"2\">说明</td></tr><tr><td colspan=\"2\">\\{n\\}</td><td>匹配n次</td><td>BRE</td><td colspan=\"2\">go{\\2}\\gle</td><td colspan=\"2\">google</td></tr><tr><td colspan=\"2\">\\{n,\\}</td><td>匹配最少n次</td><td>BRE</td><td colspan=\"2\">go{\\2,\\}gle</td><td colspan=\"2\">google, google, goooo</td></tr><tr><td colspan=\"2\">\\{n,m\\}</td><td>匹配n到m次</td><td>BRE</td><td colspan=\"2\">go{\\2,4}\\gle</td><td colspan=\"2\">google, google, goooo</td></tr><tr><td colspan=\"2\">{n}</td><td>匹配n次</td><td>ERE</td><td colspan=\"2\">go{2}gle</td><td colspan=\"2\">google</td></tr><tr><td colspan=\"2\">{n,}</td><td>匹配最少n次</td><td>ERE</td><td colspan=\"2\">go{2,}gle</td><td colspan=\"2\">google, google, goooo</td></tr><tr><td colspan=\"2\">{n,m}</td><td>匹配n到m次</td><td>ERE</td><td colspan=\"2\">go{2,4}gle</td><td colspan=\"2\">google, google, goooo</td></tr><tr><td colspan=\"2\">|</td><td>以或逻辑连接多个匹配</td><td>ERE</td><td colspan=\"2\">good|bon</td><td colspan=\"2\">匹配 good 或 bon</td></tr><tr><td colspan=\"2\">\\</td><td>转义字符</td><td>BRE</td><td colspan=\"2\">\\*</td><td colspan=\"2\">*</td></tr><tr><td>元字符</td><td colspan=\"4\">含义</td><td>类型</td><td>举例</td><td>说明</td></tr><tr><td colspan=\"2\">^</td><td colspan=\"3\">非（仅用于启始字符）</td><td>BRE</td><td>^[^xyz]</td><td>匹配xy</td></tr><tr><td colspan=\"2\">-</td><td colspan=\"3\">用于指明字符范围(不能是首字符和尾字符)</td><td>BRE</td><td>[a-zA-Z]</td><td>匹配任</td></tr><tr><td colspan=\"2\">\\</td><td colspan=\"3\">转义字符</td><td>BRE</td><td>[\\.]\\</td><td>.</td></tr></table>",
        "bbox": [
            147,
            294,
            1000,
            885
        ],
        "page_idx": 7
    },
    {
        "type": "table",
        "img_path": "",
        "table_caption": [],
        "table_footnote": [],
        "bbox": [
            142,
            86,
            1000,
            583
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "任 意 个 普 通 字 符",
        "bbox": [
            147,
            627,
            850,
            646
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "大 ： 匹 配 任 何 字 符 和 任 何 数 目 的 字 符",
        "bbox": [
            144,
            678,
            850,
            695
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "? · 匹 配 单 一 数 目 的 任 何 字 符",
        "bbox": [
            147,
            697,
            848,
            715
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "> 行 的 开 始",
        "bbox": [
            147,
            717,
            848,
            733
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "$\\$ 1$ 行 的 结 束",
        "bbox": [
            147,
            736,
            848,
            751
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "[…] 在 […] 列 表 中 的 任 意 一 个 字 符",
        "bbox": [
            147,
            753,
            848,
            770
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "[^…] 不在列表中的任一字符",
        "bbox": [
            147,
            772,
            369,
            789
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "[! ] ： 匹 配 除 了 [! ] 之 外 的 任 意 一 个 字 符 ， ! 表 示 非 的 意 思",
        "bbox": [
            144,
            804,
            848,
            821
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "=*\" 能 匹 配 文 件 或 目 录 名 中 的 66 。",
        "bbox": [
            147,
            824,
            838,
            840
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "“*”不能匹配首字符是“.”的文件或目录名",
        "bbox": [
            147,
            843,
            465,
            859
        ],
        "page_idx": 8
    },
    {
        "type": "text",
        "text": "$ 代 表 变 量 值 置 换 ",
        "bbox": [
            146,
            875,
            850,
            892
        ],
        "page_idx": 8
    },
    {
        "type": "table",
        "img_path": "images/36dec5bbc95b0522a68a5bf7b0eb755a094482f37b3a2e7896e71cd713aa157c.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>$</td><td></td><td>$PATH</td></tr><tr><td>$</td><td>echo</td><td>${mname}</td></tr><tr><td>$</td><td></td><td>nname=bigdata</td></tr><tr><td>$</td><td>echo</td><td>${mname}</td></tr></table>",
        "bbox": [
            147,
            93,
            853,
            183
        ],
        "page_idx": 9
    },
    {
        "type": "table",
        "img_path": "images/643501a2a06a7a8c19638356621268029c10bf1b74322a6c3f0c352ab0412a2f.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"3\">特 点</td><td>(</td><td colspan=\"3\">characteristic</td><td>)</td></tr><tr><td>解</td><td></td><td></td><td>释</td><td></td><td></td><td></td><td>性</td></tr><tr><td>速</td><td></td><td></td><td>度</td><td></td><td></td><td></td><td>慢</td></tr><tr><td>组</td><td colspan=\"2\">合</td><td>、</td><td colspan=\"3\">灵</td><td>活</td></tr><tr><td>Tab</td><td>键</td><td>与</td><td>历</td><td>史</td><td colspan=\"2\">命</td><td>令</td></tr><tr><td>脚</td><td colspan=\"2\">本</td><td>与</td><td colspan=\"3\">函</td><td>数</td></tr><tr><td>子</td><td></td><td></td><td>程</td><td></td><td></td><td></td><td>序</td></tr></table>",
        "bbox": [
            146,
            236,
            853,
            363
        ],
        "page_idx": 9
    },
    {
        "type": "text",
        "text": "命令行执行过程",
        "bbox": [
            147,
            367,
            275,
            382
        ],
        "page_idx": 9
    },
    {
        "type": "table",
        "img_path": "images/465055c63139246978be5884b66640de9159f6756cc2a48fa72277d0bb236f1d.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>将</td><td>命</td><td>令</td><td>行</td><td>分</td><td>成</td><td>单</td><td>个</td><td>命</td><td>令</td><td>词</td></tr><tr><td>展</td><td></td><td>开</td><td></td><td></td><td>别</td><td></td><td></td><td>名</td><td></td><td></td></tr><tr><td>展</td><td>开</td><td>大</td><td>括</td><td>号</td><td>中</td><td>的</td><td>声</td><td>明</td><td>(</td><td>{}</td></tr><tr><td>展</td><td>开</td><td>颚</td><td>化</td><td></td><td>声</td><td></td><td>明</td><td></td><td>(</td><td>~</td></tr></table>",
        "bbox": [
            147,
            398,
            843,
            470
        ],
        "page_idx": 9
    },
    {
        "type": "table",
        "img_path": "images/3afa85af89b14c5bcb855c970df53fa1b4a54d272e221ac130d283a470c7b06b.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"3\">命 令 替 换 ($() 或 “”)</td></tr><tr><td colspan=\"3\">再 次 把 命 令 行 分 成 命 令 词</td></tr><tr><td colspan=\"3\">展 开 文 件 通 配 (*、?、[abc] 等 等)</td></tr><tr><td colspan=\"3\">准 备 I/0 重 定 向 (&lt;、&gt;</td></tr><tr><td colspan=\"3\">运 行 命 令 !</td></tr><tr><td colspan=\"3\">显 示 当 前 Shell 可 见 的 全 局 变 量</td></tr><tr><td colspan=\"2\">export</td><td>[-p]</td></tr></table>",
        "bbox": [
            147,
            473,
            843,
            601
        ],
        "page_idx": 9
    },
    {
        "type": "table",
        "img_path": "images/8a9ecb025b8f69306c1a18543d3a67b54e28f15084b19f54238422e225013184.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>定义 变量 值的 同时 声明 为 全局 变量 export &lt; 变量 名 1= 值 1&gt; [&lt; 变量 名 2= 值 2&gt; ...] 声 明 已 经 赋 值 的 某 个 ( 些 ) 局 部 变 量 为 全 局 变 量 export &lt; 变量 名 1&gt; [&lt; 变量 名 2&gt; ...] 声 明 已 经 赋 值 的 某 个 ( 些 ) 全 局 变 量 为 局 部 变 量 export -n &lt; 变量 名 1&gt; [&lt; 变量 名 2&gt; ...]</td></tr></table>",
        "bbox": [
            147,
            602,
            848,
            713
        ],
        "page_idx": 9
    },
    {
        "type": "text",
        "text": "变量概念 ",
        "text_level": 1,
        "bbox": [
            147,
            755,
            258,
            777
        ],
        "page_idx": 9
    },
    {
        "type": "text",
        "text": "Shell 变量就是计算机中用于记录一个值（不一定是数值，也可以是字符或字符串）的符号，而这些符号将用于不同的运算处理中。通常变量与值是一对一的关系，可以通过表达式读取它的值并赋值给其它变量，也可以直接指定数值赋值给任意变量。为了便于运算和处理大部分的编程语言会区分变量的类型，用于分别记录数值、字符或者字符串等等数据类型",
        "bbox": [
            144,
            821,
            855,
            892
        ],
        "page_idx": 9
    },
    {
        "type": "text",
        "text": "Shell 中的变量也基本如此，有不同类型（但不用专门指定类型名），可以参与运算，有作用域限定。",
        "bbox": [
            144,
            93,
            850,
            129
        ],
        "page_idx": 10
    },
    {
        "type": "text",
        "text": "变量的作用域即变量的有效范围（比如一个函数中、一个源文件中或者全局范围），在该范围内只能有一个同名变量。一旦离开则该变量无效，如同不存在这个变量一般。",
        "bbox": [
            144,
            143,
            853,
            180
        ],
        "page_idx": 10
    },
    {
        "type": "text",
        "text": "Shell 变 量 大 致 可 以 分 为 三 类内 部 变 量 ： 由 系 统 提 供 ， 用 户 只 能 使 用 不 能 修 改 。用 户 变 量 ： 由 用 户 建 立 和 修 改 ， 在 shell 脚 本 编 写 中 会 经 常 用 到 。环境变量：这些变量决定了用户工作的环境，它们不需要用户去定义，可以直接在 shell中 使 用 ， 其 中 某 些 变 量 用 户 可 以 修 改 。变量的操作",
        "bbox": [
            144,
            195,
            853,
            305
        ],
        "page_idx": 10
    },
    {
        "type": "table",
        "img_path": "images/0536e695b11d309596acdebad749bd94578fb63b88be318d3fd77cf65e71f787.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>变</td><td>量</td><td></td><td>替</td><td></td><td>换</td><td></td><td>扩</td><td></td><td>展</td></tr><tr><td>变</td><td></td><td></td><td>量</td><td></td><td></td><td>测</td><td></td><td></td><td>试</td></tr><tr><td>变</td><td>量</td><td>的</td><td>字</td><td></td><td>符</td><td></td><td>串</td><td>操</td><td>作</td></tr><tr><td>变</td><td>量</td><td></td><td>的</td><td></td><td>间</td><td></td><td>接</td><td>引</td><td>用</td></tr><tr><td>变</td><td>量</td><td></td><td>的</td><td></td><td>数</td><td></td><td>值</td><td>计</td><td>算</td></tr><tr><td>$[expression]</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>$(expression))</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>expr</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>let</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>declare</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>-i</td></tr><tr><td>输</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>入</td></tr><tr><td>变</td><td></td><td></td><td>量</td><td></td><td></td><td>赋</td><td></td><td></td><td>值</td></tr><tr><td>name=value</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>readonly</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>从</td><td>标</td><td></td><td>准</td><td></td><td>输</td><td>入</td><td></td><td>读</td><td>取</td></tr><tr><td>read</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>输</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>出</td></tr><tr><td>echo</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>printf</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr></table>",
        "bbox": [
            144,
            319,
            853,
            675
        ],
        "page_idx": 10
    },
    {
        "type": "table",
        "img_path": "images/a730f7dfebc838bf3d7e8189fdabbb7e839d05e7a4f5e656a3517289ea8818ef.jpg",
        "table_caption": [
            "变量替换扩展"
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>Use Default Values</td><td>${var:-word}</td><td>若 var 存在且非空,则值为$var; 若 word, 但 var 的值不变。</td></tr><tr><td>Assign Default Values</td><td>${var:=word}</td><td>若 var 存在且非空,则值为$var; 若 word, 且 var 被赋值 word。</td></tr><tr><td></td><td></td><td></td></tr><tr><td>Display Error if Null or Unset</td><td>${var:?word}</td><td>若 var 存在且非空,则值为 $var; 若 v 息 word,并终止脚本。</td></tr><tr><td>Use Alternate Value</td><td>${var:+word}</td><td>若 var 存在且非空,则值为 word; 若变。</td></tr></table>",
        "bbox": [
            144,
            753,
            1000,
            895
        ],
        "page_idx": 10
    },
    {
        "type": "table",
        "img_path": "",
        "table_caption": [],
        "table_footnote": [],
        "bbox": [
            144,
            90,
            1000,
            288
        ],
        "page_idx": 11
    },
    {
        "type": "table",
        "img_path": "images/5858d712a5426a6e573b0c3b8300685b6ab9b9aeb0c03e5249ae5415888f8217.jpg",
        "table_caption": [
            "字符串计数、截取 "
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>${var}</td><td>返回字符串变量 var 的长度</td></tr><tr><td>${var:m}</td><td>返回${var}中从第 m 个字符到最后的部分</td></tr><tr><td>${var:m:len}</td><td>返回${var}中从第 m 个字符开始，长度为 len 的部分</td></tr><tr><td>${var#pattern}</td><td>删除${var}中开头部分与 pattern 匹配的最小部分</td></tr><tr><td>${var##pattern}</td><td>删除${var}中开头部分与 pattern 匹配的最大部分</td></tr><tr><td>${var%pattern}</td><td>删除${var}中结尾部分与 pattern 匹配的最小部分</td></tr><tr><td>${var%%pattern}</td><td>删除${var}中结尾部分与 pattern 匹配的最大部分</td></tr></table>",
        "bbox": [
            146,
            384,
            1000,
            690
        ],
        "page_idx": 11
    },
    {
        "type": "table",
        "img_path": "images/4514340594c97bd1abcae8d31ce6b1b7ea421e8f5cebc389574a6130a3a5bccd.jpg",
        "table_caption": [
            "字符串替换 "
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>${var/old/new}</td><td>用 new 替换${var}中第一次出现的 old</td></tr><tr><td>${var//old/new}</td><td>用 new 替换${var}中所有的 old(全局替换)</td></tr><tr><td>${var/#old/new}</td><td>用 new 替换${var}中开头部分与 old 匹配的部分</td></tr><tr><td>${var/%old/new}</td><td>用 new 替换${var}中结尾部分与 old 匹配的部分</td></tr></table>",
        "bbox": [
            146,
            719,
            1000,
            892
        ],
        "page_idx": 11
    },
    {
        "type": "text",
        "text": "old 中 可 以 使 用 通 配 符 。",
        "bbox": [
            235,
            92,
            840,
            109
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "（ 2 ） var 可 以 是 $@$ 或 * ， 表 示 对 每 个 位 置 参 数 进 行 替 换eval",
        "bbox": [
            235,
            111,
            848,
            146
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "eval arg1 [arg2] .. [argN] ",
        "bbox": [
            144,
            161,
            853,
            179
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "listpage=\"ls -l | more\" ",
        "bbox": [
            147,
            181,
            850,
            198
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "eval $listpage ",
        "bbox": [
            147,
            200,
            850,
            216
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "eval newstr=\\$$str2 ",
        "bbox": [
            144,
            250,
            852,
            266
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "eval echo \\$${x}_URL ",
        "bbox": [
            147,
            269,
            850,
            285
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "对 参 数 进 行 两 次 扫 描 和 替 换",
        "bbox": [
            144,
            319,
            850,
            336
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "将 所 有 的 参 数 连 接 成 一 个 表 达 式 ， 并 计 算 或 执 行 该 表 达 式",
        "bbox": [
            169,
            338,
            850,
            355
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "参 数 中 的 任 何 变 量 都 将 被 展 开",
        "bbox": [
            216,
            357,
            850,
            373
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "变量的间接引用",
        "bbox": [
            147,
            376,
            275,
            392
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "通过str2的值来引用str1的值",
        "bbox": [
            146,
            409,
            389,
            425
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "str1=\"Hello World\" ",
        "bbox": [
            144,
            441,
            853,
            458
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "str2 $\\cdot ^ { = }$ str1 ",
        "bbox": [
            147,
            461,
            850,
            475
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "echo $str2 ",
        "bbox": [
            147,
            480,
            850,
            494
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "eval newstr=\\$$str2 ",
        "bbox": [
            147,
            498,
            850,
            512
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "echo $newstr ",
        "bbox": [
            147,
            517,
            850,
            531
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "Hello World ",
        "bbox": [
            147,
            536,
            850,
            549
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "或",
        "bbox": [
            147,
            554,
            169,
            568
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "eval echo \\$$str2 ",
        "bbox": [
            147,
            571,
            850,
            586
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "Hello World ",
        "bbox": [
            147,
            590,
            850,
            605
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "＃ bash2.0 以 上 才 支 持",
        "bbox": [
            147,
            609,
            850,
            624
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "newstr=${!str2} ",
        "bbox": [
            147,
            627,
            850,
            643
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "echo $newstr ",
        "bbox": [
            147,
            646,
            850,
            661
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "Hello World ",
        "bbox": [
            147,
            665,
            850,
            678
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "或",
        "bbox": [
            147,
            684,
            169,
            697
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "echo ",
        "bbox": [
            147,
            703,
            850,
            717
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "Hello World ",
        "bbox": [
            147,
            721,
            850,
            734
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "shell变量的分类",
        "bbox": [
            147,
            739,
            280,
            753
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "用 户 自 定 义 变 量",
        "bbox": [
            144,
            771,
            850,
            787
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "由 用 户 自 己 定 义 、 修 改 和 使 用",
        "bbox": [
            147,
            790,
            850,
            806
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "Shell 环 境 变 量",
        "bbox": [
            147,
            809,
            850,
            824
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "由 系 统 维 护 ， 用 于 设 置 用 户 的 Shell 工 作 环 境",
        "bbox": [
            147,
            827,
            850,
            841
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "只 有 少 数 的 变 量 用 户 可 以 修 改 其 值",
        "bbox": [
            147,
            845,
            850,
            860
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "位 置 参 数 变 量 （ Positional Parameters ）",
        "bbox": [
            147,
            864,
            838,
            879
        ],
        "page_idx": 12
    },
    {
        "type": "text",
        "text": "通 过 命 令 行 给 程 序 传 递 执 行 参 数",
        "bbox": [
            144,
            883,
            850,
            898
        ],
        "page_idx": 12
    },
    {
        "type": "table",
        "img_path": "images/6cc149646954f287832c242a8752e57e10098f5e2a687e55cffbe8b10aa6f709.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"9\">可 用 shift 命 令 实 现 位 置 参 数 的 迁 移</td></tr><tr><td colspan=\"9\">专 用 参数 数 变 量 (Special Parameters)</td></tr><tr><td colspan=\"9\">Bash 预 定 义 的 特 殊 变 量</td></tr><tr><td colspan=\"9\">用 户 不 能 修 改 其 值</td></tr><tr><td colspan=\"9\">位置参数变量</td></tr></table>",
        "bbox": [
            144,
            91,
            853,
            184
        ],
        "page_idx": 13
    },
    {
        "type": "table",
        "img_path": "images/c689524610915dc38010999d2525afdb3d19f903eeea905f416c68390890a59f.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"2\">是 一 组 特 殊 的 内 置 变 量跟 在 脚 本 名 后 面 的 用 空 格 隔 开 的 每 个 字 符 串$1 表 示 第 1 个 参数 值 , ... , $9 表 示 第 9 个 参数 值${10} 表 示 第 10 个 参数 值, $\\{11\\} 表 示第 11 个 参数 值, ... ...位 置 参 数 的 用 途从 shell 命 令 / 脚 本 的 命 令 行 接 受 参数在 调 用 shell 函数 时 为 其 传 递 参数专用参数变量</td></tr></table>",
        "bbox": [
            144,
            199,
            850,
            344
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "$* 将所有位置参量看成一个字符串(以空格间隔)。",
        "bbox": [
            144,
            361,
            840,
            378
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "$@ 将 每 个 位 置 参 量 看 成 单 独 的 字 符 串 （ 以 空 格 间 隔 ） 。",
        "bbox": [
            146,
            381,
            840,
            397
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "“$*” 将 所 有 位 置 参 量 看 成 一 个 字 符 串 （ 以 $\\$ 105$ 间 隔 ） 。",
        "bbox": [
            161,
            399,
            838,
            416
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "$\" \\$ 0$ 将 每 个 位 置 参 量 看 成 单 独 的 字 符 串 （ 以 空 格 间 隔 ） 。",
        "bbox": [
            161,
            418,
            838,
            434
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "$0 命令行上输入的 Shell 程序名。",
        "bbox": [
            146,
            437,
            838,
            451
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "$# 表 示 命 令 行 上 参 数 的 个 数 。",
        "bbox": [
            146,
            455,
            838,
            470
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "进 程 状 态 相 关",
        "bbox": [
            146,
            473,
            848,
            489
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "$\\$ 7$ 表 示 上 一 条 命 令 执 行 后 的 返 回 值",
        "bbox": [
            146,
            492,
            848,
            508
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "$$ 当前 进程 的 进程号",
        "bbox": [
            146,
            510,
            848,
            526
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "$\\$ !$ 显 示 运 行 在 后 台 的 最 后 一 个 作 业 的 PID",
        "bbox": [
            146,
            529,
            848,
            545
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "$_ 在此之前执行的命令或脚本的最后一个参数",
        "bbox": [
            146,
            546,
            848,
            563
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "shift 命令",
        "bbox": [
            146,
            565,
            226,
            581
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "Shift[n] ",
        "text_level": 1,
        "bbox": [
            146,
            599,
            211,
            615
        ],
        "page_idx": 13
    },
    {
        "type": "table",
        "img_path": "images/9ec227275c1c4324dcfded387055819df045662bdc0dc9f04f63b64055fcbcdc.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"3\">将位置参量列表依次左移n次，缺省为左移一次</td></tr><tr><td colspan=\"3\">一旦位置参量列表被移动，最左端的那个参数就会从列表中删除</td></tr><tr><td colspan=\"3\">经常与循环结构语句一起使用，以便遍历每一个位置参数</td></tr><tr><td colspan=\"3\">$? : 返回上一条语句或脚本执行的状态</td></tr><tr><td>0</td><td>:</td><td>成功</td></tr><tr><td>1</td><td>-</td><td>255</td></tr><tr><td>exit</td><td>命</td><td>命</td></tr><tr><td>exit</td><td colspan=\"2\">命令用于退出脚本或当前 Shell</td></tr><tr><td>exit</td><td></td><td>n</td></tr></table>",
        "bbox": [
            144,
            631,
            848,
            795
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "n 是一 个从 0 到 255 的整数",
        "bbox": [
            146,
            799,
            848,
            815
        ],
        "page_idx": 13
    },
    {
        "type": "text",
        "text": "0 表 示 成 功 退 出 ， 非 零 表 示 遇 到 某 种 失 败",
        "bbox": [
            146,
            816,
            848,
            833
        ],
        "page_idx": 13
    },
    {
        "type": "phonetic",
        "text": "返回 值 被 保存 在 状态 变 量 $? 中",
        "bbox": [
            146,
            835,
            848,
            851
        ],
        "page_idx": 13
    },
    {
        "type": "page_number",
        "text": "0 ",
        "bbox": [
            146,
            888,
            161,
            901
        ],
        "page_idx": 13
    },
    {
        "type": "page_number",
        "text": "",
        "bbox": [
            828,
            889,
            838,
            901
        ],
        "page_idx": 13
    },
    {
        "type": "table",
        "img_path": "images/7ebc0b08b0ba05e9f626ccd71980b8644bfc7502ea8ae205e10ab0b80413a7be.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>执</td><td></td><td>行</td><td></td><td></td><td>正</td><td></td><td></td><td>确</td></tr><tr><td>1</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>:</td></tr><tr><td>通</td><td></td><td>用</td><td></td><td></td><td>错</td><td></td><td></td><td>误</td></tr><tr><td>126</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>:</td></tr><tr><td>命</td><td>令</td><td>或</td><td>脚</td><td>本</td><td>没有</td><td>执行</td><td>行权</td><td>限</td></tr><tr><td>127</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td>:</td></tr><tr><td>命</td><td></td><td>令</td><td></td><td>没</td><td></td><td>找</td><td></td><td>到</td></tr><tr><td>read</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr></table>",
        "bbox": [
            146,
            91,
            853,
            239
        ],
        "page_idx": 14
    },
    {
        "type": "table",
        "img_path": "images/90a570c5c9bc35440804fda33806bfd223de41b75ba8fd2ed6c2f8f3dc062d71.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"3\">从键盘输入内容为变量赋值</td></tr><tr><td colspan=\"3\">read [-p]&quot; 信息&quot;] [var1 var2 ...]</td></tr><tr><td colspan=\"3\">若省略变量名,则将输入的内容存入REPLY变量</td></tr><tr><td colspan=\"3\">结合不同引号为变量赋值</td></tr><tr><td colspan=\"3\">双引号&quot;：允许通过$符号引用其他变量值</td></tr><tr><td colspan=\"3\">单引号&#x27;：禁止引用其他变量值,$视为普通字符</td></tr><tr><td colspan=\"3\">反撇号、`、`：将命令执行的结果输出给变量</td></tr><tr><td colspan=\"3\">只读变量</td></tr></table>",
        "bbox": [
            146,
            254,
            850,
            403
        ],
        "page_idx": 14
    },
    {
        "type": "table",
        "img_path": "images/8006282caf9dc331a0d1864f8259db7a2a7d5f8ce3dda142f3e35e932d29ca88.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"2\">readonly</td><td>variable</td></tr><tr><td>使</td><td>用</td><td>echo</td></tr><tr><td colspan=\"3\">多行内容中不能出现双引号，否则 echo 提前结束</td></tr><tr><td colspan=\"3\">若确实需要使用双引号，需使用转义字符：\\”</td></tr><tr><td>使</td><td>用</td><td>here file</td></tr><tr><td colspan=\"3\">.END_可以是任意字符串，只要上下一致即可多行内容中不能出现内容为.END_开始的行，否则 cat 提前结束</td></tr></table>",
        "bbox": [
            147,
            418,
            852,
            546
        ],
        "page_idx": 14
    },
    {
        "type": "text",
        "text": "2.2 变量声明",
        "text_level": 1,
        "bbox": [
            144,
            588,
            305,
            611
        ],
        "page_idx": 14
    },
    {
        "type": "text",
        "text": "这里简单举例说明在 Shell 中如何创建一个变量：",
        "bbox": [
            144,
            687,
            526,
            703
        ],
        "page_idx": 14
    },
    {
        "type": "text",
        "text": "使用 declare 命令创建一个变量名为 tmp 的变量：",
        "bbox": [
            144,
            720,
            534,
            737
        ],
        "page_idx": 14
    },
    {
        "type": "text",
        "text": "declare tmp ",
        "bbox": [
            144,
            753,
            250,
            769
        ],
        "page_idx": 14
    },
    {
        "type": "text",
        "text": "其实也可以不用 declare 预声明一个变量，直接即用即创建，这里只是告诉你 declare 的作用，这在创建其它指定类型的变量（如数组）时会用到。",
        "bbox": [
            144,
            785,
            850,
            820
        ],
        "page_idx": 14
    },
    {
        "type": "text",
        "text": "2.3 变量名 ",
        "text_level": 1,
        "bbox": [
            144,
            99,
            278,
            122
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "变量名的命名须遵循如下规则：",
        "bbox": [
            144,
            166,
            389,
            181
        ],
        "page_idx": 15
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "首个字符必须为字母（a-z，A-Z）。",
            " 中间不能有空格，可以使用下划线（_）。",
            "不能使用标点符号。",
            " 不能使用 bash 里的关键字（可用 help 命令查看保留关键字）。"
        ],
        "bbox": [
            174,
            199,
            700,
            313
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "2.4 变量赋值 ",
        "text_level": 1,
        "bbox": [
            144,
            338,
            305,
            360
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "变 量 赋 值 （ 定 义 变 量 ）",
        "bbox": [
            144,
            403,
            840,
            420
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "varName=Value ",
        "bbox": [
            146,
            423,
            282,
            437
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "export ",
        "bbox": [
            146,
            441,
            206,
            456
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "varName=Value ",
        "bbox": [
            712,
            441,
            848,
            455
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "引 用 变 量",
        "bbox": [
            146,
            458,
            490,
            474
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "$varName ",
        "bbox": [
            759,
            460,
            848,
            473
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "一 般 地 ， 所 有 的 Shell 变 量 都 是 字 符 串 。",
        "bbox": [
            144,
            478,
            838,
            493
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "当 变 量 的 值 仅 仅 包 含 数 字 时 才 允 许 进 行 数 值 计 算 。",
        "bbox": [
            144,
            495,
            838,
            512
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "在较新的 bash 中，可是使用 declare 或 typeset 命令声明变量及其属性，但一般不需要声明。而且为了使脚本兼容于不同的 shell，在没有必要的情况下尽量不使用变量声明。",
        "bbox": [
            144,
            514,
            847,
            550
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "变量赋值时，变量名不加美元符号（$，PHP 语言中变量需要）。",
        "bbox": [
            144,
            602,
            648,
            619
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "使用 $=$ 号赋值运算符，将变量 tmp 赋值为 shiyanlou。",
        "bbox": [
            144,
            636,
            568,
            652
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "# 正确的赋值方法",
        "bbox": [
            144,
            669,
            290,
            683
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "tmp=shiyanlou ",
        "bbox": [
            146,
            702,
            275,
            717
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "# 错误的赋值方法",
        "bbox": [
            146,
            734,
            290,
            749
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "tmp $=$ shiyanlou ",
        "bbox": [
            146,
            768,
            284,
            782
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "注意:变量名和等号之间不能有空格。",
        "bbox": [
            144,
            800,
            428,
            815
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "除了直接赋值，还可以用语句给变量赋值，如for 循环中：",
        "bbox": [
            144,
            833,
            596,
            848
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "for file in `ls /etc` ",
        "bbox": [
            146,
            865,
            289,
            879
        ],
        "page_idx": 15
    },
    {
        "type": "text",
        "text": "2.5 变量取值 ",
        "text_level": 1,
        "bbox": [
            147,
            134,
            305,
            156
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "变量的名字就是变量保存值的地方。引用变量的值就叫做变量取值。",
        "bbox": [
            144,
            200,
            672,
            218
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "如果 variable 是一个变量的名字，那么 $variable 就是引用这个变量的值，即这变量所包含的数据。",
        "bbox": [
            144,
            231,
            848,
            268
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "$variable 事实上只是 $\\$ 1$ {variable} 的简写形式。在某些上下文中 $variable 可能会引起错误，这时候就需要用 ${variable} 了。",
        "bbox": [
            144,
            284,
            848,
            319
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "读取变量的值，使用 echo 命令和 $\\$ 9$ 符号（ $\\$ 5$ 符号用于表示引用一个变量的值，初学者经常忘记输入）：",
        "bbox": [
            144,
            335,
            848,
            370
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "echo $tmp ",
        "bbox": [
            146,
            387,
            243,
            405
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "myname $=$ \"shiyanlou\" ",
        "bbox": [
            146,
            419,
            329,
            437
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "echo $myname ",
        "bbox": [
            147,
            451,
            280,
            469
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "echo ${myname} ",
        "bbox": [
            147,
            485,
            292,
            501
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "echo ${myname}Good ",
        "bbox": [
            147,
            518,
            337,
            533
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "echo $mynameGood ",
        "bbox": [
            147,
            551,
            324,
            565
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "myname $=$ \"miao\" ",
        "bbox": [
            147,
            583,
            290,
            599
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "echo ${myname} ",
        "bbox": [
            147,
            615,
            292,
            632
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "使用readonly 命令可以将变量定义为只读变量，只读变量的值不能被改变。 下面的例子尝试更改只读变量，结果报错：",
        "bbox": [
            144,
            682,
            847,
            715
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "#!/bin/bash ",
        "bbox": [
            147,
            733,
            247,
            747
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "myUrl=\"http://www.shiyanlou.com\" ",
        "bbox": [
            147,
            766,
            443,
            782
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "readonly myUrl ",
        "bbox": [
            147,
            799,
            278,
            815
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "myUrl=http://www.shiyanlou.com ",
        "bbox": [
            147,
            832,
            430,
            848
        ],
        "page_idx": 16
    },
    {
        "type": "text",
        "text": "变量的查询、显示和取消 ",
        "bbox": [
            147,
            864,
            346,
            879
        ],
        "page_idx": 16
    },
    {
        "type": "table",
        "img_path": "images/95e0c0efd0ddd138f4bd08fd9135cbe1c711592da80a5509dd543553a485d65f.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"3\">显示当前已经定义的所有变量</td></tr><tr><td colspan=\"3\">所有有环境变量：env</td></tr><tr><td colspan=\"3\">所有变量和函数（包括环境变量）：set</td></tr><tr><td colspan=\"3\">显示某些个变量的值</td></tr><tr><td>echo $NAME1</td><td>[$NAME2]</td><td>......]</td></tr><tr><td colspan=\"3\">取消变量的声明或赋值</td></tr><tr><td>unset</td><td></td><td>&lt;NAME&gt;</td></tr></table>",
        "bbox": [
            144,
            91,
            853,
            221
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "1. 子进程（Child Process）的本质",
        "text_level": 1,
        "bbox": [
            146,
            255,
            428,
            272
        ],
        "page_idx": 17
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " 当你在 Shell 中运行 bash -c 'command' 时，会启动一个 全新的子 Shell 进程。",
            "子进程会继承父进程的 环境变量（export 导出的变量），但 不会继承父进程的私有变量。"
        ],
        "bbox": [
            174,
            288,
            847,
            356
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "引用",
        "bbox": [
            146,
            372,
            188,
            388
        ],
        "page_idx": 17
    },
    {
        "type": "table",
        "img_path": "images/382eeeb7bc44518f29fe28eb4ba7441d8a2de580b94d3bb4f0578a6bd7f5932f.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"11\">在bash中，有些字符具有特殊含义，如果需要忽略这些字符的特殊含义，就必须使用引用</td></tr><tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr><tr><td>引用</td><td>可以</td><td>通过</td><td>下</td><td>面</td><td>三</td><td>种</td><td>方</td><td>式</td><td>实</td><td>现</td></tr><tr><td></td><td>使</td><td>用</td><td>转</td><td>义</td><td></td><td>字</td><td>符</td><td>:</td><td>\\</td><td></td></tr><tr><td></td><td>使</td><td>用</td><td>单</td><td>引</td><td>号</td><td>:</td><td>&#x27;</td><td></td><td>&#x27;</td><td></td></tr><tr><td></td><td>使</td><td>用</td><td>双</td><td>引</td><td>号</td><td>:</td><td>“</td><td></td><td>”</td><td></td></tr></table>",
        "bbox": [
            144,
            404,
            847,
            513
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "转义字符的引用方法就是直接在字符前加反斜杠。例：\\$，\\‘，\\“，\\\\，\\ ，\\!",
        "bbox": [
            144,
            517,
            739,
            533
        ],
        "page_idx": 17
    },
    {
        "type": "table",
        "img_path": "images/5d1a7e6ca3e33eaa372a2593a5e7578d40354388a8cc066eee75fc8ff9f984da.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>强</td><td colspan=\"3\">引</td><td>用</td></tr><tr><td>单</td><td>引</td><td>号</td><td>对</td><td>是 强 引 用</td></tr><tr><td colspan=\"5\">单引号对中的字符都将作为普通字符,但不允许出现另外的单引号。</td></tr><tr><td colspan=\"5\">弱引用</td></tr></table>",
        "bbox": [
            144,
            548,
            848,
            621
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "双引号对是弱引用",
        "bbox": [
            146,
            624,
            292,
            639
        ],
        "page_idx": 17
    },
    {
        "type": "table",
        "img_path": "images/4cb13fa48e934209dac52184942f843c48f9c346d6a45f716d4fe7035af94365.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td colspan=\"3\">双引号对中的部分字符仍保留特殊含义</td></tr><tr><td>$（ 美元 符 号）</td><td>-</td><td>变量 扩展</td></tr><tr><td>（ 反 引 号）</td><td>-</td><td>命 令 替 换</td></tr><tr><td>（ 反 斜 线）</td><td>-</td><td>禁止 单个 字符 扩展</td></tr><tr><td>！（ 叹 号）</td><td>-</td><td>历史 命 令 替 换</td></tr></table>",
        "bbox": [
            144,
            640,
            848,
            732
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "4.1 环境变量",
        "text_level": 1,
        "bbox": [
            144,
            775,
            304,
            797
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "简单理解了变量的概念，就很容易理解环境变量了。环境变量的作用域比自定义变量的要大，如Shell 的环境变量作用于自身和它的子进程。在所有的 UNIX 和类UNIX 系统中，每个进程都有其各自的环境变量设置，且默认情况下，当一个进程被创建时，除了创建过程",
        "bbox": [
            144,
            841,
            848,
            895
        ],
        "page_idx": 17
    },
    {
        "type": "text",
        "text": "中明确指定的话，它将继承其父进程的绝大部分环境设置。Shell 程序也作为一个进程运行在操作系统之上，而我们在 Shell 中运行的大部分命令都将以 Shell 的子进程的方式运行。",
        "bbox": [
            144,
            93,
            848,
            129
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "通常我们会涉及到的变量类型有三种：",
        "bbox": [
            144,
            143,
            443,
            160
        ],
        "page_idx": 18
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "当前 Shell 进程私有用户自定义变量，如上面我们创建的 tmp 变量，只在当前Shell 中有效。",
            " Shell 本身内建的变量。",
            " 从自定义变量导出的环境变量。"
        ],
        "bbox": [
            174,
            177,
            847,
            277
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "也有三个与上述三种环境变量相关的命令：set，env，export。这三个命令很相似，都是用于打印环境变量信息，区别在于涉及的变量范围不同。详见下表：",
        "bbox": [
            144,
            294,
            850,
            328
        ],
        "page_idx": 18
    },
    {
        "type": "table",
        "img_path": "images/f0efc7dd784b88be9736ab59105317c3b6b447849dfa4fa723f9ded6d21da12a.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>命令</td><td>说明</td></tr><tr><td>set</td><td>显示当前 Shell 所有变量，包括其内建环境变量（与 Shell 外观等相关），用户自定义变量及导出的环境变量。</td></tr><tr><td>env</td><td>显示与当前用户相关的环境变量，还可以让命令在指定环境中运行。</td></tr><tr><td>export</td><td>显示从 Shell 中导出成环境变量的变量，也能通过它将自定义变量导出为环境变量。</td></tr></table>",
        "bbox": [
            146,
            329,
            763,
            564
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "vimdiff env.txt export.txt set.txt ",
        "bbox": [
            144,
            579,
            413,
            595
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "使用vimdiff 工具比较导出的几个文件的内容，退出 vimdiff 需要按下 Esc 后输入 :q 即可退出。",
        "bbox": [
            144,
            645,
            848,
            678
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "关于哪些变量是环境变量，可以简单地理解成在当前进程的子进程有效则为环境变量，否则不是（有些人也将所有变量统称为环境变量，只是以全局环境变量和局部环境变量进行区分，我们只要理解它们的实质区别即可）。我们这里用 export 命令来体会一下，先在Shell 中设置一个变量 temp=shiyanlou，然后再新创建一个子 Shell 查看 temp 变量的值：",
        "bbox": [
            144,
            696,
            850,
            769
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "环境变量",
        "text_level": 1,
        "bbox": [
            144,
            818,
            223,
            833
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "环 境 变 量 定 义 Shell 的 运 行 环 境 ， 保 证 Shell 命 令 的 正 确 执 行 。",
        "bbox": [
            144,
            883,
            840,
            898
        ],
        "page_idx": 18
    },
    {
        "type": "text",
        "text": "Shell 用环境变量来 确 定 查找路 径 、 注册目 录 、终端类型 、终端名 称 、 用 户 名 等 。所有环境变量都是全局变量（即可以传递给 Shell 的子进程），并可以由用户重新设置。",
        "bbox": [
            144,
            93,
            838,
            129
        ],
        "page_idx": 19
    },
    {
        "type": "table",
        "img_path": "images/8c70ec3f3467dd8dc326a26c22122471c617cb64c4965b4669e28ec8965a08c9.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>变量名</td><td>含义</td></tr><tr><td>HOME</td><td>用户主目录</td></tr><tr><td>LOGNAME</td><td>登录名</td></tr><tr><td>USER</td><td>用户名，与登录名相同</td></tr><tr><td>PWD</td><td>当前目录/工作目录名</td></tr><tr><td>MAIL</td><td>用户的邮箱路径名</td></tr><tr><td>HOSTNAME</td><td>计算机的主机名</td></tr><tr><td>INPUTRC</td><td>默认的键盘映像</td></tr><tr><td>SHELL</td><td>用户所使用的 shell 的路径名</td></tr><tr><td>LANG</td><td>默认语言</td></tr><tr><td>HISTSIZE</td><td>history 所能记住的命令的最多个数</td></tr><tr><td>PATH</td><td>shell 查找用户输入命令的路径(目录列表)</td></tr><tr><td>PS1、PS2</td><td>shell 一级、二级命令提示符</td></tr></table>",
        "bbox": [
            144,
            145,
            998,
            697
        ],
        "page_idx": 19
    },
    {
        "type": "text",
        "text": "注意：为了与普通变量区分，通常我们习惯将环境变量名设为大写。",
        "bbox": [
            144,
            746,
            670,
            762
        ],
        "page_idx": 19
    },
    {
        "type": "text",
        "text": "4.2 变量时效 ",
        "text_level": 1,
        "bbox": [
            144,
            778,
            253,
            793
        ],
        "page_idx": 19
    },
    {
        "type": "text",
        "text": "当关机后，或者关闭当前的 shell 之后，环境变量就失效了。怎样才能让环境变量永久生效呢？",
        "bbox": [
            144,
            810,
            847,
            845
        ],
        "page_idx": 19
    },
    {
        "type": "text",
        "text": "按变量的生存周期来划分，Linux 变量可分为两类：",
        "bbox": [
            144,
            863,
            544,
            878
        ],
        "page_idx": 19
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "1. 永久的：需要修改配置文件，变量永久生效；",
            "2. 临时的：使用 export 命令行声明即可，变量在关闭 shell 时失效。"
        ],
        "bbox": [
            176,
            93,
            715,
            141
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "这里介绍两个重要文件 /etc/bashrc（有的 Linux 没有这个文件） 和 /etc/profile ，它们分别存放的是 shell 变量和环境变量。还有要注意区别的是每个用户目录下的一个隐藏文件：",
        "bbox": [
            144,
            159,
            847,
            193
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "这个 .profile 只对当前用户永久生效。因为它保存在当前用户的 Home 目录下，当切换用户时，工作目录可能一并被切换到对应的目录中，这个文件就无法生效。而写在 /etc/profile 里面的是对所有用户永久生效，所以如果想要添加一个永久生效的环境变量，只需要打开 /etc/profile，在最后加上要添加的环境变量。",
        "bbox": [
            144,
            210,
            848,
            281
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "4.3 PATH 变量",
        "text_level": 1,
        "bbox": [
            144,
            306,
            324,
            328
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "你可能很早之前就有疑问，我们在 Shell 中输入一个命令，Shell 是怎么知道去哪找到这个命令然后执行的呢？这是通过环境变量 PATH 来进行搜索的，熟悉 Windows 的用户可能知道 Windows 中的也是有这么一个 PATH 环境变量。这个 PATH 里面就保存了 Shell 中执行的命令的搜索路径。",
        "bbox": [
            144,
            372,
            847,
            443
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "1. 查看 PATH 内容",
        "text_level": 1,
        "bbox": [
            176,
            461,
            332,
            476
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "查看PATH 环境变量的内容：",
        "bbox": [
            144,
            493,
            369,
            508
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "echo $PATH ",
        "bbox": [
            146,
            526,
            250,
            539
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "默认情况下你会看到如下输出：",
        "bbox": [
            144,
            592,
            388,
            607
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/ games ",
        "bbox": [
            144,
            625,
            806,
            659
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "如果你还记得 Linux 目录结构那一节的内容，你就应该知道上面这些目录下放的是哪一类文件了。通常这一类目录下放的都是可执行文件，当我们在 Shell 中执行一个命令时，系统就会按照 PATH 中设定的路径按照顺序依次到目录中去查找，如果存在同名的命令，则执行先找到的那个。",
        "bbox": [
            144,
            709,
            847,
            780
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "回到上一级目录，也就是 shiyanlou 家目录，当再想运行那两个程序时，会发现提示命令找不到，除非加上命令的完整路径，但那样很不方便，如何做到像使用系统命令一样执行自己创建的脚本文件或者程序呢？那就要将命令所在路径添加到PATH 环境变量了。",
        "bbox": [
            144,
            797,
            847,
            850
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "3. 自定义 PATH 变量",
        "text_level": 1,
        "bbox": [
            176,
            866,
            349,
            882
        ],
        "page_idx": 20
    },
    {
        "type": "text",
        "text": "现在，我们添加自定义路径到“ PATH ”环境变量。在前面我们应该注意到 PATH 里面的路径是以: 作为分割符的，所以我们可以这样添加自定义路径：",
        "bbox": [
            144,
            93,
            850,
            129
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "PATH=$PATH:/home/shiyanlou/mybin ",
        "bbox": [
            146,
            143,
            460,
            161
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "你可能会意识到这样还并没有很好的解决问题，因为我给 PATH 环境变量追加了一个路径，它也只是在当前 Shell 有效，我一旦退出终端，再打开就会发现又失效了。有没有方法让添加的环境变量全局有效？或者每次启动 Shell 时自动执行上面添加自定义路径到 PATH的命令？下面我们就来说说后一种方式——让它自动执行。",
        "bbox": [
            144,
            177,
            857,
            250
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "在每个用户的 home 目录中有一个 Shell 每次启动时会默认执行一个配置脚本，以初始化环境，包括添加一些用户自定义环境变量等等。实验楼的环境使用的 Shell 是 zsh，它的配置文件是 .zshrc，相应的如果使用的 Shell 是 Bash，则配置文件为 .bashrc。它们在 etc下还都有一个或多个全局的配置文件，不过我们一般只修改用户目录下的配置文件。Shell的种类有很多，可以使用cat /etc/shells 命令查看当前系统已安装的 Shell。",
        "bbox": [
            144,
            266,
            853,
            356
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "我们可以简单地使用下面命令直接添加内容到.zshrc 中：",
        "bbox": [
            146,
            373,
            584,
            388
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "echo \"PATH=$PATH:/home/shiyanlou/mybin\" >> .zshrc ",
        "bbox": [
            146,
            405,
            600,
            420
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "上述命令中 $> >$ 表示将标准输出以追加的方式重定向到一个文件中，注意前面用到的 $>$ 是以覆盖的方式重定向到一个文件中，使用的时候一定要注意分辨。在指定文件不存在的情况下都会创建新的文件。",
        "bbox": [
            144,
            470,
            852,
            525
        ],
        "page_idx": 21
    },
    {
        "type": "text",
        "text": "4. 修改 PATH 变量",
        "text_level": 1,
        "bbox": [
            176,
            541,
            332,
            557
        ],
        "page_idx": 21
    },
    {
        "type": "table",
        "img_path": "images/80b2d5c1c43c40f8f14bddcdb09334a88b6612aadb8c535afbaa004d5e1d8246.jpg",
        "table_caption": [
            "PATH 变量的修改有以下几种方式："
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>变量设置方式</td><td>说明</td></tr><tr><td>${变量名#匹配字串}</td><td>从头向后开始匹配，删除符合匹配字串的最短数据</td></tr><tr><td>${变量名##匹配字串}</td><td>从头向后开始匹配，删除符合匹配字串的最长数据</td></tr><tr><td>${变量名%匹配字串}</td><td>从尾向前开始匹配，删除符合匹配字串的最短数据</td></tr><tr><td>${变量名%%匹配字串}</td><td>从尾向前开始匹配，删除符合匹配字串的最长数据</td></tr><tr><td>${变量名/旧的字串/新的字串}</td><td>将符合旧字串的第一个字串替换为新的字串</td></tr><tr><td>${变量名//旧的字串/新的字串}</td><td>将符合旧字串的全部字串替换为新的字串</td></tr></table>",
        "bbox": [
            147,
            590,
            764,
            888
        ],
        "page_idx": 21
    },
    {
        "type": "table",
        "img_path": "",
        "table_caption": [],
        "table_footnote": [],
        "bbox": [
            147,
            90,
            763,
            263
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "4.4 环境变量删除",
        "text_level": 1,
        "bbox": [
            144,
            278,
            289,
            294
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "可以使用unset 命令删除一个环境变量：",
        "bbox": [
            146,
            311,
            460,
            326
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "unset mypath ",
        "bbox": [
            146,
            344,
            265,
            360
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "4.5 环境变量立即生效",
        "text_level": 1,
        "bbox": [
            144,
            376,
            322,
            392
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "前面我们在 Shell 中修改了一个配置脚本文件之后（比如 zsh 的配置文件 home 目录下的.zshrc），每次都要退出终端重新打开甚至重启主机之后其才能生效，很是麻烦，我们可以使用source 命令来让其立即生效，如：",
        "bbox": [
            144,
            409,
            847,
            462
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "cd /home/shiyanlou ",
        "bbox": [
            146,
            480,
            315,
            494
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "source .zshrc ",
        "bbox": [
            146,
            513,
            260,
            526
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "source 命令还有一个别名就是 .，上面的命令如果替换成 . 的方式就该是：",
        "bbox": [
            144,
            577,
            715,
            593
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": ". ./.zshrc ",
        "bbox": [
            147,
            611,
            220,
            624
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "在使用.的时候，需要注意与表示当前路径的那个点区分开。",
        "bbox": [
            144,
            643,
            603,
            658
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "注意第一个点后面有一个空格，而且后面的文件必须指定完整的绝对或相对路径名source 则不需要。",
        "bbox": [
            144,
            676,
            843,
            709
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "总结",
        "text_level": 1,
        "bbox": [
            146,
            728,
            186,
            741
        ],
        "page_idx": 22
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " 加./：显式执行当前目录下的脚本/程序。",
            " 不加 ./：要求命令位于 PATH 包含的目录中。"
        ],
        "bbox": [
            174,
            760,
            552,
            808
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "位置变量用于接收从命令行传递到脚本的参数： $\\$ 0$ ， $\\$ 1$ ， $\\$ 2$ ， $\\$ 3\\ldots$ ",
        "bbox": [
            144,
            826,
            667,
            841
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "$\\$ 0$ 就是脚本文件自身的名字， $\\$ 1$ 是第一个参数， $\\$ 2$ 是第二个参数， $\\$ 3$ 是第三个参数，然后是第四个。 $\\$ 9$ 之后的位置参数就必须用大括号括起来了，比如， $\\$ \\{10\\}$ ，${11}，",
        "bbox": [
            144,
            859,
            836,
            892
        ],
        "page_idx": 22
    },
    {
        "type": "text",
        "text": "${12}。 ",
        "bbox": [
            147,
            93,
            201,
            109
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "位置参数实例",
        "text_level": 1,
        "bbox": [
            147,
            126,
            258,
            142
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "在运行脚本的时候，有时候是需要参数的，这里我们学习如何获取参数。",
        "bbox": [
            144,
            159,
            705,
            174
        ],
        "page_idx": 23
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " $# ： 传递到脚本的参数个数",
            " $* ： 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过 9 个",
            " $$ ： 脚本运行的当前进程 ID 号",
            " $! ： 后台运行的最后一个进程的进程 ID 号",
            " $@ ： 与 $\\$ ^ { \\star }$ 相同,但是使用时加引号，并在引号中返回每个参数",
            " $\\$ 7$ ： 显示最后命令的退出状态。 0 表示没有错误，其他任何值（如 1）表明有错误。"
        ],
        "bbox": [
            174,
            191,
            847,
            407
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "用户工作环境",
        "bbox": [
            176,
            425,
            287,
            439
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "用户登录系统时，Shell为用户自动定义唯一的工作环境并对该环境进行维护直至用户注 销 。",
        "bbox": [
            174,
            458,
            847,
            492
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "该环境将定义如身份、工作场所和正在运行的进程等特性。这些特性由指定的环境变量 值 定 义 。",
        "bbox": [
            174,
            495,
            845,
            527
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "用 户 工 作 环 境 有 登 录 环 境 和 非 登 录 环 境 之 分 。登录环境是指用户登录系统时的工作环境，此时的 Shell对登录用户而言是主Shell。非 登 录 环 境 是 指 用 户 再 调 用 子 Shell 时 所 使 用 的 用 户 环 境 。",
        "bbox": [
            174,
            532,
            847,
            583
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "对 所 有 用 户 进 行 设 置/etc/profile/etc/bashrc",
        "bbox": [
            174,
            587,
            847,
            639
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "只 对 当 前 用 户 进 行 设 置",
        "bbox": [
            174,
            661,
            847,
            677
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "~/.bash_profile",
        "bbox": [
            174,
            681,
            304,
            695
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "~/.bashrc ",
        "bbox": [
            174,
            700,
            258,
            713
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "通 常 ， 个 人 bash 环 境 设 置 都 定 义 在 ~/.bashrc 文 件 里登录shell和非登录shell的启动过程",
        "bbox": [
            174,
            717,
            847,
            751
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "Login shell ",
        "bbox": [
            174,
            769,
            847,
            784
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "/etc/profile  /etc/profile.d/*.sh ",
        "bbox": [
            174,
            788,
            847,
            802
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "$HOME/.bash_profile ",
        "bbox": [
            176,
            824,
            356,
            839
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "$HOME/.bashrc ",
        "bbox": [
            176,
            862,
            310,
            875
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": " ",
        "bbox": [
            524,
            862,
            537,
            873
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "/etc/bashrc ",
        "bbox": [
            751,
            862,
            848,
            875
        ],
        "page_idx": 23
    },
    {
        "type": "text",
        "text": "通常用户在 bash 下输入命令时不必把命令输全， shell 就能判断出你所要输入的命令。该功能的核心思想是：bash 根据用户已输入的信息来查找以这些信息开头的命令，从而试图完成当前命令的输入工作。用来执行这项功能的键是 Tab 键，按下一次 Tab 键后，bash 就试图完成整个命令的输入，如果不成功，可以再按一次 Tab 键，这时bash 将 列 出 所 有 能 够 与 当 前 输 入 字 符 相 匹 配 的 命 令 列 表 。通常用户在 bash 下输入命令时不必把命令输全， shell 就能判断出你所要输入的命令。该功能的核心思想是：bash 根据用户已输入的信息来查找以这些信息开头的命令，从而试图完成当前命令的输入工作。用来执行这项功能的键是 Tab 键，按下一次 Tab 键后，bash 就试图完成整个命令的输入，如果不成功，可以再按一次 Tab 键，这时bash 将 列 出 所 有 能 够 与 当 前 输 入 字 符 相 匹 配 的 命 令 列 表 。键 盘 快 捷 键最 简 单 的 方 法 是 用 上 下 方 向 键 、 <PgUp> 和 <PgDn> 键 来 查 看 历 史 命 令如果需要的话，可以使用键盘上的编辑功能键对显示在命令行上的命令进行编辑感 叹 号 的 用 法用 !! 执 行 最 近 执 行 过 的 命 令用 ! < 命 令 事 件 号 $>$ 执 行 已 经 运 行 过 的 命 令用 ! <已经使用过的命令前面的部分 $>$ 执行已经运行过的以该字符串开头的最近的命令命令别名",
        "bbox": [
            174,
            181,
            855,
            513
        ],
        "page_idx": 24
    },
    {
        "type": "code",
        "sub_type": "code",
        "code_caption": [],
        "code_body": "允许用户按照自己喜欢的方式对命令进行自定义格式  \nalias [alias_name='original_command']说明  \nalias_name 是用户给命令取的别名。original_command是原来的命令和参数。若命令中包含空格或其他的特殊字符串必须使用引号。在定义别名时，等号两边不允许有空格。不带任何参数的alias命令显示当前已定义的所有别名。可以使用unalias alias_name命令取消某个别名的定义。如果用户需要别名的定义在每次登录时均有效，应该将其写入用户自家目录下的.bashrc 文件 中",
        "guess_lang": "txt",
        "bbox": [
            174,
            527,
            850,
            750
        ],
        "page_idx": 24
    },
    {
        "type": "code",
        "sub_type": "code",
        "code_caption": [],
        "code_body": "定义 别 名 举 例  \nalias Ih='ls -lh'  \nalias grep='grep --color=auto'  \nalias gitcam='git commit -a -m'",
        "guess_lang": "shell",
        "bbox": [
            174,
            769,
            853,
            843
        ],
        "page_idx": 24
    },
    {
        "type": "text",
        "text": "注 意若系统中有一个命令，同时又定义了一个与之同名的别名（例如，系统中有 grep命令，且又 定义了 grep 的 别 名 ） ，则别 名 将优先 于 系 统 中原有 的 命 令 的 执 行 。",
        "bbox": [
            176,
            845,
            850,
            898
        ],
        "page_idx": 24
    },
    {
        "type": "header",
        "text": "Non-Login ",
        "bbox": [
            176,
            112,
            270,
            127
        ],
        "page_idx": 24
    },
    {
        "type": "header",
        "text": "$HOME/.bashrc ",
        "bbox": [
            176,
            130,
            312,
            143
        ],
        "page_idx": 24
    },
    {
        "type": "header",
        "text": "命令补全 ",
        "bbox": [
            176,
            149,
            253,
            164
        ],
        "page_idx": 24
    },
    {
        "type": "header",
        "text": "shell ",
        "bbox": [
            806,
            112,
            850,
            126
        ],
        "page_idx": 24
    },
    {
        "type": "header",
        "text": " ",
        "bbox": [
            524,
            131,
            539,
            143
        ],
        "page_idx": 24
    },
    {
        "type": "header",
        "text": "/etc/bashrc ",
        "bbox": [
            752,
            131,
            850,
            145
        ],
        "page_idx": 24
    },
    {
        "type": "text",
        "text": "要想临时使用系统中的命令而非别名，应该在命令前添加“\\”字符，例如，$ \\grep 命令将运行系统中原来的 grep 命令而不是 grep 别名，它不在输出中显示颜色。",
        "bbox": [
            176,
            93,
            850,
            130
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "运算 ",
        "text_level": 1,
        "bbox": [
            144,
            152,
            206,
            174
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "Bash 变 量 没 有 严 格 的 类 型 定 义本 质 上 Bash 变 量 都 是 字 符 串若一个字面常量或变量的值是纯数字的，不包含字母或其他字符， Bash可以将其视为长整 型 值 ， 并 可 做 算 数 运 算 和 比 较 运 算 。Bash 也 允 许 显 式 地 声 明 整 型 变 量declare -i 变 量 名",
        "bbox": [
            144,
            236,
            848,
            344
        ],
        "page_idx": 25
    },
    {
        "type": "table",
        "img_path": "images/081c888b50dca276f3f54733ce43d6383c374f344a628b63bdb0a795ca40c019.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>+、-、*、/ (四则运算)</td></tr><tr><td>**、% (幂运算和模运算,取余数)</td></tr><tr><td>&lt;&lt;、&gt;&gt; (按位左移和按位右移)</td></tr><tr><td>&amp;、^、| (按位与、按位异或和按位或)</td></tr><tr><td>=、+=、-=、*=、/=、%=&gt;&lt;&lt;=、&gt;==、&amp;=、^=、|= (赋值运算)</td></tr><tr><td>&lt;、&gt;、&lt;=、&gt;=、==、!= (比较操作符)</td></tr><tr><td>&amp;&amp;、|| (逻辑与和逻辑或)</td></tr></table>",
        "bbox": [
            173,
            344,
            707,
            520
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "注：按位运算是以二进制形式进行的。",
        "bbox": [
            178,
            538,
            584,
            558
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "Bash本身没有计算功能，需要借助其他命令完成表达式的运算，包括算术运算和逻辑运算。在表达式中使用了各种运算符，具体于使用的命令有关，参看相关命令的 man帮助手册。expr 命令可以进行一些算术运算，包括加、减、乘、除等。也可以进行一些逻辑运算。",
        "bbox": [
            144,
            602,
            857,
            657
        ],
        "page_idx": 25
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "计算结果赋值给变量时，要注意使用反撇号（与~ 在同一个键）",
            "表达式和运算符之间要有空格， $\\$ 0+\\$ 6$ 写成 $\\$ 0+\\$ 6$ 不行",
            "乘号（*）前边必须加反斜杠（)才能实现乘法运算 ",
            "除法是取整的除法"
        ],
        "bbox": [
            174,
            673,
            697,
            785
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "Echo中单引号的原则是不管里面的内容是什么都原样输出，不能识别通配符、变量、命令等。",
        "bbox": [
            144,
            804,
            847,
            838
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "双引号就比单引号人性化一点，可以识别变量和特殊转义符，进行一步翻译再输出，同时我这里再强调一下在shell脚本中使用双引号必须结合 $\\$ 5$ 、/和`这三个来申明变量、引入特",
        "bbox": [
            144,
            854,
            848,
            890
        ],
        "page_idx": 25
    },
    {
        "type": "text",
        "text": "色符号和加如命令，这样才可以直接被编译器识别的。",
        "bbox": [
            144,
            93,
            564,
            109
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "逻辑运算：",
        "bbox": [
            144,
            126,
            231,
            142
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "（但这里要注意逻辑运算的话，&和|与一般的逻辑运算||和&&不同吧！不要将这两个搞混）",
        "bbox": [
            144,
            159,
            848,
            193
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "在 expr 命令中，| 不是逻辑或，而是一个 模式匹配（Alternation）运算符，其行为如下：",
        "bbox": [
            144,
            210,
            857,
            227
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": ". 规则：",
        "bbox": [
            174,
            243,
            257,
            259
        ],
        "page_idx": 26
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "o 若 ARG1 非空且非零 返回 ARG1",
            "o 否则 返回 ARG2"
        ],
        "bbox": [
            236,
            275,
            544,
            324
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "返回值：直接返回 ARG1 或 ARG2 的原始值，不是布尔值 1/0。",
        "bbox": [
            174,
            341,
            695,
            357
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": ". expr 中的 & 运算符",
        "bbox": [
            146,
            374,
            317,
            391
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "在 expr 中，& 是 “匹配”运算符（Match Operator），其行为如下：",
        "bbox": [
            144,
            407,
            695,
            423
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": ". 规则：",
        "bbox": [
            174,
            439,
            255,
            455
        ],
        "page_idx": 26
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "o 若 ARG1 和 ARG2 都 非空且非零 返回 ARG1",
            "o 否则 返回 0"
        ],
        "bbox": [
            236,
            472,
            638,
            520
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "返回值：ARG1 或 0，不是布尔值 1/0。",
        "bbox": [
            174,
            538,
            510,
            554
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "另外的大小比较为真时返回 1 否则返回 0",
        "text_level": 1,
        "bbox": [
            144,
            571,
            465,
            586
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "Zsh 中的问题",
        "text_level": 1,
        "bbox": [
            144,
            604,
            258,
            619
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "在 Zsh 中，当您运行 ret=`\\expr length \"hello\"`，反引号将会被解析成一个命令并尝试执行 expr length \"hello\"。然而，Zsh 报告了 command not found: 5 的错误。这表明，Zsh 在尝试解析输出结果时没有正确处理返回值。因为 expr length \"hello\"` 输出的是一个数字（5），Zsh 错误地将这个数字当作一个命令来执行。",
        "bbox": [
            144,
            636,
            857,
            708
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "Bash 中的行为",
        "text_level": 1,
        "bbox": [
            146,
            725,
            268,
            740
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "Bash 在处理这个命令时表现得更宽容。Bash 会将反引号中的命令输出正确地捕获，并将结果（即5）赋值给ret 变量，而不会尝试将其解释为命令。",
        "bbox": [
            144,
            757,
            848,
            791
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "2. 反引号与 $\\$ 0$ 语法的替代",
        "text_level": 1,
        "bbox": [
            144,
            809,
            361,
            825
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "虽然反引号 ` 在大多数情况下能正常工作，但它并不总是最清晰和最可靠的选择。尤其是当命令返回数值或字符串时，反引号可能会带来意料之外的结果。现代 Shell（包括 Zsh和 Bash）更推荐使用 $() 代替反引号，因为它更容易嵌套和理解，并且更少出现解析错",
        "bbox": [
            144,
            841,
            850,
            895
        ],
        "page_idx": 26
    },
    {
        "type": "text",
        "text": "误。）",
        "bbox": [
            147,
            93,
            193,
            108
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "1. 为什么建议加双引号？",
        "text_level": 1,
        "bbox": [
            147,
            126,
            339,
            142
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "(1) 防止变量值中的空格或特殊字符被解析",
        "text_level": 1,
        "bbox": [
            144,
            159,
            478,
            175
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "如果 $PATH 中包含空格或特殊字符（如 *、?、$），不加引号时 Shell 会对其进行分词或扩展：",
        "bbox": [
            174,
            191,
            847,
            225
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "(2) 避免通配符扩展",
        "text_level": 1,
        "bbox": [
            144,
            243,
            302,
            259
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": " 如果$PATH 包含* 或? 等通配符，不加引号时Shell 会尝试文件匹配：",
        "bbox": [
            174,
            275,
            752,
            292
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "(3) 确保变量引用完整 ",
        "text_level": 1,
        "bbox": [
            144,
            307,
            319,
            325
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "双引号能明确变量边界，避免与后续字符混淆：",
        "bbox": [
            176,
            341,
            571,
            357
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "# 不加引号时，若变量名后紧跟字母或下划线，会被误认为变量名的一部分",
        "bbox": [
            144,
            374,
            732,
            388
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "2. 什么情况下可以省略双引号？",
        "text_level": 1,
        "bbox": [
            144,
            407,
            391,
            422
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "当变量值绝对不包含空格、通配符或特殊字符时（如纯字母数字和 : 的PATH），可以不加引号：",
        "bbox": [
            174,
            439,
            836,
            473
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "echo PATH=/usr/bin:/bin $> >$ .zshrc # 安全",
        "bbox": [
            144,
            491,
            492,
            506
        ],
        "page_idx": 27
    },
    {
        "type": "table",
        "img_path": "images/ea3b3937c9cdb5ff0fc91f1ce2bb8f29d12e736ddb11b854124dd1797f5f796b.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>命令执行结果</td><td>$?取值</td><td>逻辑表达式值</td></tr><tr><td>成功</td><td>0</td><td>1（真）</td></tr><tr><td>失败</td><td>1</td><td>0（假）</td></tr></table>",
        "bbox": [
            147,
            539,
            763,
            675
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "expr命令除了进行算术和逻辑运算之外（不是我想到&&与||，另外也并没有提到取非、异或、按位运算），还可以进行字符串的操作。",
        "bbox": [
            144,
            690,
            836,
            725
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "Test 命令",
        "text_level": 1,
        "bbox": [
            146,
            775,
            223,
            789
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "Bash对于逻辑表达式的求值需要借助 test命令完成。。test命令中逻辑运算符有两套，分为数值型和字符型，另外还有对于文件进行判断的运算符，和表达式复合的运算符。",
        "bbox": [
            144,
            807,
            836,
            841
        ],
        "page_idx": 27
    },
    {
        "type": "text",
        "text": "主要区别",
        "text_level": 1,
        "bbox": [
            146,
            859,
            221,
            873
        ],
        "page_idx": 27
    },
    {
        "type": "table",
        "img_path": "images/0c9d27fab33e67a0d4f144eefaf763bf5e9089acfc45c5be43defa6c2737f37a.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>特性</td><td>test 10 -It 20 (或 [ 10 -It 20 ])</td><td>expr 10 \\\\&lt; 20</td></tr><tr><td>用途</td><td>Shell 条件测试</td><td>通用表达式计算</td></tr><tr><td>是 Shell 内置吗?</td><td>☐是(高效)</td><td>☐外部命令(较慢)</td></tr><tr><td>比较类型</td><td>数值比较</td><td>字符串比较(但数字仍可正确比较)</td></tr><tr><td>返回值(输出)</td><td>返 回 0 (true) 或 1 (false)</td><td>输出 1 (true) 或 0 (false),但 $?仍然是 0/1</td></tr><tr><td>符号</td><td>-It (必须用 - 开头的运算符)</td><td>&lt; (必须转义为 \\&lt; )</td></tr><tr><td>适用场景</td><td>if 条件判断</td><td>需要计算表达式并获取结果</td></tr></table>",
        "bbox": [
            139,
            114,
            860,
            524
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "test -n $f echo $\\$ 7$ test -z $f echo $? ",
        "bbox": [
            144,
            539,
            433,
            555
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "结果都为0！奇怪。 ",
        "bbox": [
            144,
            571,
            294,
            588
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "bc是一个独立的bc是一个较为完整的工具，为Bash提供了更强的计算能力，提供了完备的类似C的编程语法的计算器，可以在交互式界面、文本或管道的方式方便的进行一些运算。支持多进制转换，任意精度调整，打印控制，函数支持，逻辑控制等。",
        "bbox": [
            144,
            605,
            847,
            659
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "算 术 运 算 扩 展",
        "bbox": [
            144,
            674,
            848,
            690
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "$[expression] ",
        "bbox": [
            147,
            694,
            263,
            709
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "$((expression)) ",
        "bbox": [
            147,
            712,
            272,
            728
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "用 $[···] ， $\\$ (( \\cdots ) )$ 进 行整数 运 算时，括 号内变 量前 的美元符号 $\\$ 1$ 可 以省 略。",
        "bbox": [
            144,
            730,
            836,
            746
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "注 意 ${···} ， $(···) ， $[···] ， $((···)) 的 不 同 作 用",
        "bbox": [
            147,
            749,
            847,
            766
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "双小括号",
        "text_level": 1,
        "bbox": [
            146,
            808,
            258,
            829
        ],
        "page_idx": 28
    },
    {
        "type": "text",
        "text": "双小括号中可以使用类似 C 语言的表达式，((exp))的格式更符合一般使用习惯。",
        "bbox": [
            144,
            873,
            756,
            890
        ],
        "page_idx": 28
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "这种扩展计算是整数型的计算，不支持浮点型。",
            "如果表达式的结果为0，那么返回的退出状态码为1，或者是\"假\"，而一个非零值的表达式所返回的退出状态码将为 0，或者是\"true\"。若是逻辑判断，表达式 exp为真则为 1,假则为 0。",
            "只要括号中的运算符、表达式符合 C 语言运算规则，都可用在$((exp))中，甚至是三目运算符",
            "作不同进位(如二进制、八进制、十六进制)运算时，输出结果全都自动转化成了十进制。"
        ],
        "bbox": [
            174,
            93,
            852,
            282
        ],
        "page_idx": 29
    },
    {
        "type": "code",
        "sub_type": "code",
        "code_caption": [],
        "code_body": "echo $((16#5f)) ",
        "guess_lang": "lisp",
        "bbox": [
            144,
            298,
            278,
            313
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "95 #16 进制转 10 进制",
        "bbox": [
            144,
            331,
            337,
            347
        ],
        "page_idx": 29
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " 用于算术运算比较，双括号中的变量可以不使用$符号前缀。",
            "括号内支持多个表达式用逗号分开"
        ],
        "bbox": [
            174,
            395,
            670,
            445
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "中括号",
        "text_level": 1,
        "bbox": [
            147,
            470,
            233,
            492
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "中括号也可以进行整数运算。",
        "bbox": [
            144,
            536,
            371,
            552
        ],
        "page_idx": 29
    },
    {
        "type": "equation",
        "text": "$$\n\\mathsf {b} = \\mathbb {S} [ 1 + 3 ]\n$$",
        "text_format": "latex",
        "bbox": [
            144,
            569,
            226,
            586
        ],
        "page_idx": 29
    },
    {
        "type": "equation",
        "text": "$$\ne c h o \\mathbb {S} ^ {\\mathrm {b}}\n$$",
        "text_format": "latex",
        "bbox": [
            146,
            602,
            218,
            615
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "4 ",
        "bbox": [
            146,
            634,
            161,
            648
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "Let ",
        "bbox": [
            146,
            668,
            179,
            681
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "let 内 置 命 令 用 于 算 术 运 算",
        "bbox": [
            144,
            699,
            853,
            715
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "赋 值 符 号 和 运 算 符 两 边 不 能 留 空 格 ！",
        "bbox": [
            144,
            718,
            843,
            734
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "如 果 将 字 符 串 赋 值 给 一 个 整 型 变 量 时 ， 则 变 量 的 值 为 0",
        "bbox": [
            169,
            736,
            850,
            753
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "如 果 变 量 的 值 是 字 符 串 ， 则 进 行 算 术 运 算 时 设 为 0",
        "bbox": [
            144,
            755,
            850,
            771
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "let num2=4 + 1 ",
        "bbox": [
            144,
            774,
            848,
            789
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "let \"num2=4 + 1\" # 用 引 号 忽 略 空 格 的 特 殊 含 义",
        "bbox": [
            144,
            791,
            850,
            809
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "用 let 命令进行算术运算时，最好加双引号",
        "bbox": [
            144,
            810,
            482,
            827
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "expr ",
        "bbox": [
            146,
            845,
            189,
            859
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "通 用 的 表 达 式 计 算 命 令",
        "bbox": [
            144,
            876,
            850,
            892
        ],
        "page_idx": 29
    },
    {
        "type": "text",
        "text": "表 达 式 中 参 数 与 操 作 符 必 须 以 空 格 分 开 。表 达 式 中 的 运 算 可 以 是 算 术 运 算 ， 比 较 运 算 ， 字 符 串 运 算 和 逻 辑 运 算 。",
        "bbox": [
            144,
            92,
            843,
            128
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "expr \\( 2 + 5 \\) \\* 2 – 3 # 括 号 必 须 被 转 义expr 5 \\* 3 # 乘 法 符 号 必 须 被 转 义",
        "bbox": [
            146,
            130,
            848,
            165
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "bash 只 支 持 整 数 运 算可 以 通 过 使 用 bc 或 awk 工 具 来 处 理 浮 点 数 运 算",
        "bbox": [
            146,
            167,
            850,
            202
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "$\\mathsf { m } \\boldsymbol { = }$ `awk 'BEGIN{x=2.45;y=3.123; \\ printf \"%.3f\\n\", x*y}'` ",
        "bbox": [
            146,
            204,
            850,
            239
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "echo $m $\\mathsf { n } { = } \\$ 1$ (echo \"scale=3; 13/2\" | bc ) ",
        "bbox": [
            147,
            241,
            850,
            278
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "echo $n ",
        "bbox": [
            147,
            279,
            850,
            293
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "Printf 命令",
        "text_level": 1,
        "bbox": [
            146,
            330,
            235,
            344
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "printf format 输 出 参 数 列 表",
        "bbox": [
            144,
            362,
            850,
            379
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "printf \"%-12.5f\\n\" 123.456 ",
        "bbox": [
            146,
            381,
            850,
            399
        ],
        "page_idx": 30
    },
    {
        "type": "table",
        "img_path": "images/8f815ade51754c5f5eeb352fa117890ed7495ddd601cb43f2f38c0d8fe576608.jpg",
        "table_caption": [
            "printf命令的格式说明符 "
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>c</td><td>字符型</td><td>g/G</td><td>浮点数（自动）</td></tr><tr><td>d</td><td>十进制整数</td><td>o</td><td>八进制</td></tr><tr><td>e/E</td><td>浮点数（科学计数法）</td><td>s</td><td>字符串</td></tr><tr><td>f</td><td>浮点数（小数形式）</td><td>x/X</td><td>十六进制</td></tr></table>",
        "bbox": [
            157,
            443,
            502,
            499
        ],
        "page_idx": 30
    },
    {
        "type": "table",
        "img_path": "images/a0c7e5328909c7a738d98cb7987deda54469d5ff706ad93d4f16198218df9017.jpg",
        "table_caption": [
            "format中还可以使用"
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>\\a</td><td>警铃</td><td>\\t</td><td>水平制表符</td></tr><tr><td>\\b</td><td>退后一格</td><td>\\v</td><td>垂直制表符</td></tr><tr><td>\\n</td><td>换行</td><td>\\</td><td>反斜杠</td></tr><tr><td>\\f</td><td>换页</td><td>\\&quot;</td><td>双引号</td></tr><tr><td>\\r</td><td>回车</td><td>\\\\&quot;</td><td>百分号</td></tr></table>",
        "bbox": [
            157,
            514,
            502,
            585
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "数组变量",
        "text_level": 1,
        "bbox": [
            146,
            613,
            221,
            629
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "使 用 declare 声 明 或 直 接 给 变 量 名 加 下 标 来 赋 值 。",
        "bbox": [
            144,
            645,
            843,
            662
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "declare -a variable ",
        "bbox": [
            146,
            665,
            848,
            680
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "variable=(item1 item2 item2 ) ",
        "bbox": [
            146,
            682,
            850,
            699
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "variable=(item1 item2 item2 ... ) ",
        "bbox": [
            146,
            702,
            850,
            717
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "variable[n]=value ",
        "bbox": [
            146,
            720,
            294,
            736
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "${variable[n]} ",
        "bbox": [
            147,
            739,
            263,
            755
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "Bash 2.x 以上支持一维数组，下标从0 开始。",
        "bbox": [
            144,
            790,
            497,
            806
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "Declare ",
        "bbox": [
            146,
            822,
            213,
            838
        ],
        "page_idx": 30
    },
    {
        "type": "text",
        "text": "declare [ 选 项 ] variable[=value] ",
        "bbox": [
            144,
            854,
            850,
            872
        ],
        "page_idx": 30
    },
    {
        "type": "table",
        "img_path": "images/118ef7e3c8e606875d1096586642f77b9e71d54e8ff8474a5afad989372d16e3.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>选项</td><td>含义</td></tr><tr><td>-r</td><td>将变量设为只读 (readonly)</td></tr><tr><td>-x</td><td>将变量输出到子 shell 中 (export 为全局变量)</td></tr><tr><td>-i</td><td>将变量设为整型 (integer)</td></tr><tr><td>-a</td><td>将变量设置为一个数组 (array)</td></tr><tr><td>-f</td><td>列出函数的名字和定义 (function)</td></tr><tr><td>-F</td><td>只列出函数名</td></tr></table>",
        "bbox": [
            142,
            89,
            1000,
            395
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "条 件 测 试 可 以 判 断 某 个 特 定 条 件 是 否 满 足",
        "bbox": [
            144,
            409,
            852,
            426
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "测 试 之 后 通 常 会 根 据 不 同 的 测 试 值 选 择 执 行 不 同 任 务",
        "bbox": [
            146,
            428,
            848,
            444
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "条 件 测 试 的 种 类 ",
        "bbox": [
            147,
            447,
            850,
            463
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "命 令 成 功 或 失 败 ",
        "bbox": [
            147,
            466,
            850,
            481
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "表 达 式 为 真 或 假",
        "bbox": [
            147,
            483,
            850,
            500
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "条 件 测 试 的 值 ",
        "bbox": [
            147,
            502,
            850,
            518
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "Bash 中 没 有 布 尔 类 型 变 量",
        "bbox": [
            147,
            521,
            850,
            537
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "退 出 状 态 为 0 表 示 命 令 成 功 或 表 达 式 为 真",
        "bbox": [
            147,
            539,
            850,
            555
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "非 0 则 表 示 命 令 失 败 或 表 达 式 为 假",
        "bbox": [
            147,
            558,
            850,
            573
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "状 态 变 量 $\\$ 7$ 中 保 存 了 退 出 状 态 的 值",
        "bbox": [
            147,
            576,
            850,
            592
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "语 句 ",
        "bbox": [
            147,
            595,
            850,
            611
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "格 式 1 ： test < 测 试 表 达 式 >",
        "bbox": [
            147,
            614,
            850,
            629
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "格 式 2 ： [ < 测 试 表 达 式 > ]",
        "bbox": [
            147,
            632,
            850,
            648
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "格 式 3 ： [[ < 测 试 表 达 式 > ]] （ bash 2.x 版 本 以 上 ）",
        "bbox": [
            147,
            650,
            850,
            665
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "说 明",
        "bbox": [
            147,
            670,
            850,
            686
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "格 式 1 和 格 式 2 是 等 价 的 ， 格 式 3 是 扩 展 的 test 命 令",
        "bbox": [
            147,
            688,
            850,
            703
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "在 [[ ]] 中 可 以 使 用 通 配 符 进 行 模 式 匹 配",
        "bbox": [
            147,
            707,
            850,
            722
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "&&, ||, <, 和 $>$ 能 够 正 常 存 在 于 [[ ]] 中 ， 但 不 能 在 [] 中 出 现",
        "bbox": [
            147,
            725,
            850,
            741
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "[ 和 [[ 之 后 的 字 符 必 须 为 空 格 ， ] 和 ]] 之 前 的 字 符 必 须 为 空 格",
        "bbox": [
            147,
            744,
            850,
            759
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "要 对 整 数 进 行 关 系 运 算 也 可 以 使 用 (()) 进 行 测 试",
        "bbox": [
            147,
            762,
            850,
            777
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "条 件 测 试 表 达 式 中 可 用 的 操 作 符",
        "bbox": [
            147,
            780,
            850,
            796
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "文 件 测 试 操 作 符",
        "bbox": [
            147,
            799,
            850,
            815
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "字 符 串 测 试 操 作 符 ",
        "bbox": [
            147,
            818,
            850,
            833
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "整 数 二 元 比 较 操 作 符 ",
        "bbox": [
            147,
            837,
            850,
            852
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "使 用 逻 辑 运 算 符",
        "bbox": [
            147,
            854,
            850,
            871
        ],
        "page_idx": 31
    },
    {
        "type": "text",
        "text": "文件测试",
        "bbox": [
            147,
            873,
            221,
            889
        ],
        "page_idx": 31
    },
    {
        "type": "table",
        "img_path": "images/307700d5c4bd9210b3ac1dfad7969c6506b415cea8a5131210c9b1eee67fc245.jpg",
        "table_caption": [],
        "table_footnote": [
            "字符串测试 "
        ],
        "table_body": "<table><tr><td>[-f fname]</td><td>fname存在且是普通文件时，返回真（即返回</td></tr><tr><td>[-L fname]</td><td>fname存在且是链接文件时，返回真</td></tr><tr><td>[-d fname]</td><td>fname存在且是一个目录时，返回真</td></tr><tr><td>[-e fname]</td><td>fname（文件或目录）存在时，返回真</td></tr><tr><td>[-s fname]</td><td>fname存在且大小大于0时，返回真</td></tr><tr><td>[-r fname]</td><td>fname（文件或目录）存在且可读时，返回真</td></tr><tr><td>[-w fname]</td><td>fname（文件或目录）存在且可写时，返回真</td></tr><tr><td>[-x fname]</td><td>fname（文件或目录）存在且可执行时，返回</td></tr></table>",
        "bbox": [
            142,
            87,
            1000,
            850
        ],
        "page_idx": 32
    },
    {
        "type": "table",
        "img_path": "images/71c13866d42625288054f7d1afb6beff6f6da16f137b5fbbed104dcfc3b8513b.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>[-z string]</td><td>如果字符串string长度为0，返回真</td></tr><tr><td>[-n string]</td><td>如果字符串string长度不为0，返回真</td></tr><tr><td>[ str1 = str2]</td><td>两字符串相等（也可使用==）返回真</td></tr><tr><td>[ str1 != str2]</td><td>两字符串不等返回真</td></tr><tr><td>[[str1 == str2]]</td><td>两字符串相同返回真</td></tr><tr><td>[[str1 != str2]]</td><td>两字符串不相同返回真</td></tr><tr><td>[[str1~= str2]]</td><td>str2是str1的子串返回真</td></tr><tr><td>[[str1 &gt; str2]]</td><td>str1大于str2返回真</td></tr><tr><td>[[str1 &lt; str2]]</td><td>str1小于str2返回真</td></tr></table>",
        "bbox": [
            142,
            86,
            998,
            369
        ],
        "page_idx": 33
    },
    {
        "type": "table",
        "img_path": "images/efef892f57431a44c56f72fc6926d78534b0af3acb6cd2fefcb2cbc378158e51.jpg",
        "table_caption": [
            "字 符 串 按 从 左 到 右 对 应 字 符 的 ASCII 码 进 行 比 较整数测试"
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>[int1 -eq int2]</td><td colspan=\"2\">int1 等于 int2 返回真</td></tr><tr><td>[int1 -ne int2]</td><td colspan=\"2\">int1 不等于 int2 返回真</td></tr><tr><td>[int1 -gt int2]</td><td colspan=\"2\">int1 大于 int2 返回真</td></tr><tr><td>[int1 -ge int2]</td><td colspan=\"2\">int1 大于或等于 int2 返回真</td></tr><tr><td>[int1 -lt int2]</td><td colspan=\"2\">int1 小于 int2 返回真</td></tr><tr><td>[int1 -le int2]</td><td colspan=\"2\">int1 小于或等于 int2 返回真</td></tr><tr><td colspan=\"2\">[[int1 -eq int2]]</td><td>int1 等于 int2 返回真</td></tr><tr><td colspan=\"2\">[[int1 -ne int2]]</td><td>int1 不等于 int2 返回真</td></tr><tr><td colspan=\"2\">[[int1 -gt int2]]</td><td>int1 大于 int2 返回真</td></tr><tr><td colspan=\"2\">[[int1 -ge int2]]</td><td>int1 大于或等于 int2 返回真</td></tr><tr><td colspan=\"2\">[[int1 -lt int2]]</td><td>int1 小于 int2 返回真</td></tr><tr><td colspan=\"2\">[[int1 -le int2]]</td><td>int1 小于或等于 int2 返回真</td></tr></table>",
        "bbox": [
            144,
            420,
            998,
            770
        ],
        "page_idx": 33
    },
    {
        "type": "table",
        "img_path": "images/586d11fbd376e0677ba596d3e01193dec42d6d8d634dd0cdfecbe27d806d3662.jpg",
        "table_caption": [
            "操 作 符 两 边 必 须 留 空 格 ！"
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>((int1 == int2))</td><td>int1 等于 int2 返回真</td></tr><tr><td>((int1 != int2))</td><td>int1 不等于 int2 返回真</td></tr><tr><td>((int1 &gt; int2))</td><td>int1 大于 int2 返回真</td></tr><tr><td>((int1 &gt;= int2))</td><td>int1 大于或等于 int2 返回真</td></tr><tr><td>((int1 &lt; int2))</td><td>int1 小于 int2 返回真</td></tr><tr><td>((int1 &lt;= int2))</td><td>int1 小于或等于 int2 返回真</td></tr></table>",
        "bbox": [
            144,
            822,
            996,
            894
        ],
        "page_idx": 33
    },
    {
        "type": "table",
        "img_path": "",
        "table_caption": [],
        "table_footnote": [],
        "bbox": [
            144,
            90,
            998,
            225
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "操 作 符 两 边 的 空 格 可 省 略 ！",
        "bbox": [
            144,
            227,
            840,
            243
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "方括号前后要留空格",
        "text_level": 1,
        "bbox": [
            144,
            263,
            312,
            279
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "[] 内 不 能 使 用 通 配 符 ！",
        "bbox": [
            144,
            282,
            840,
            298
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "在 [[]] 中可以使用 shell 的通配符进行条件匹配",
        "bbox": [
            144,
            300,
            510,
            316
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "通配符与正则表达式",
        "bbox": [
            144,
            319,
            312,
            335
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "通配符",
        "text_level": 1,
        "bbox": [
            176,
            338,
            265,
            353
        ],
        "page_idx": 34
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "o 由 Shell 解析（如 bash, zsh）",
            "o 直接匹配文件名，无需外部工具",
            "o 例如 rm *.tmp 是 Shell 自身展开文件列表"
        ],
        "bbox": [
            236,
            357,
            603,
            410
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "正则表达式",
        "text_level": 1,
        "bbox": [
            176,
            412,
            300,
            426
        ],
        "page_idx": 34
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "o 由文本处理工具解析（grep, sed, awk 等）",
            "o 匹配文本内容，支持更复杂的模式"
        ],
        "bbox": [
            236,
            431,
            603,
            464
        ],
        "page_idx": 34
    },
    {
        "type": "table",
        "img_path": "images/abb8ad50cb788bd576d2cede59a8dd24619ff34fb5a0c27450c061ef1ca4e2a3.jpg",
        "table_caption": [
            "逻辑测试 "
        ],
        "table_footnote": [],
        "table_body": "<table><tr><td>[ expr1 -a expr2 ]</td><td colspan=\"2\">逻辑与，都为真时，结果为真</td></tr><tr><td>[ expr1 -o expr2 ]</td><td colspan=\"2\">逻辑或，有一个为真时，结果为真</td></tr><tr><td>[! expr ]</td><td colspan=\"2\">逻辑非</td></tr><tr><td colspan=\"2\">[ [ pattern1 &amp;&amp; pattern2 ]]</td><td>逻辑与</td></tr><tr><td colspan=\"2\">[ [ pattern1 | | pattern2 ]]</td><td>逻辑或</td></tr><tr><td colspan=\"2\">[! ! pattern ]]</td><td>逻辑非</td></tr><tr><td colspan=\"2\">(( expr1 &amp;&amp; expr2 ))</td><td>逻辑与</td></tr><tr><td colspan=\"2\">(( expr1 | | expr2 ))</td><td>逻辑或</td></tr><tr><td colspan=\"2\">([! expr ))</td><td>逻辑非</td></tr></table>",
        "bbox": [
            144,
            483,
            998,
            866
        ],
        "page_idx": 34
    },
    {
        "type": "footer",
        "text": "注 ： 不 能 在 (()) 中 做 字 符 串 比 较",
        "bbox": [
            144,
            885,
            850,
            904
        ],
        "page_idx": 34
    },
    {
        "type": "text",
        "text": "注 不 能 随 便 添 加 括 号",
        "bbox": [
            144,
            92,
            850,
            109
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "(( $x == 1 )) && [[ $name = To? ]]; echo $? ",
        "bbox": [
            144,
            130,
            850,
            145
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "此 处 的 && 并 非 逻 辑 运 算 符 ， 而 是 命 令 聚 合 （ Command Group ）",
        "bbox": [
            144,
            148,
            840,
            164
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "if 分支结构",
        "text_level": 1,
        "bbox": [
            144,
            206,
            285,
            229
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "一般是对逻辑表达式进行判断。根据逻辑表达式的真、假，分走不同的分支。这个表达式也称为条件表达式。",
        "bbox": [
            144,
            273,
            850,
            307
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "1.1 语法格式",
        "text_level": 1,
        "bbox": [
            146,
            325,
            253,
            340
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "这里才是真正所谓的逻辑判断需要&&和||",
        "bbox": [
            144,
            357,
            478,
            375
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "下面是if 分支结构的几种语法格式。",
        "bbox": [
            146,
            391,
            426,
            406
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "格式一：if",
        "bbox": [
            146,
            409,
            235,
            424
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "if cond_cmd ",
        "bbox": [
            144,
            442,
            252,
            458
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "then ",
        "bbox": [
            146,
            476,
            189,
            489
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "command1 ",
        "bbox": [
            164,
            508,
            262,
            521
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "command2 ",
        "bbox": [
            164,
            541,
            265,
            555
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            579,
            184,
            588
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "commandN ",
        "bbox": [
            164,
            606,
            267,
            621
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "fi ",
        "bbox": [
            146,
            639,
            163,
            652
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "格式二：if-else",
        "bbox": [
            144,
            703,
            275,
            720
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "if cond_cmd ",
        "bbox": [
            146,
            737,
            252,
            753
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "then ",
        "bbox": [
            146,
            771,
            189,
            784
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "command1 ",
        "bbox": [
            164,
            803,
            262,
            816
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "command2 ",
        "bbox": [
            164,
            835,
            265,
            850
        ],
        "page_idx": 35
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            873,
            184,
            883
        ],
        "page_idx": 35
    },
    {
        "type": "code",
        "sub_type": "code",
        "code_caption": [],
        "code_body": "commandN else command fi ",
        "guess_lang": "txt",
        "bbox": [
            147,
            93,
            268,
            206
        ],
        "page_idx": 36
    },
    {
        "type": "code",
        "sub_type": "code",
        "code_caption": [
            "格式三：if-elif-else"
        ],
        "code_body": "if cond_cmd  \nthen command1  \nelif con_cmd2  \nthen command2  \nelse commandN  \nfi ",
        "guess_lang": "txt",
        "bbox": [
            147,
            288,
            268,
            565
        ],
        "page_idx": 36
    },
    {
        "type": "text",
        "text": "if 其实是判断其后面的命令是否执行成功为分支条件的，因此 if 之后不一定必须是test 命令，可以是任何其他的命令，只是这些命令一般不需要其输出，因为只需要知道执行成功与否，输出并不重要，一般就通过重定向到/dev/null 解决。",
        "bbox": [
            144,
            585,
            848,
            638
        ],
        "page_idx": 36
    },
    {
        "type": "code",
        "sub_type": "code",
        "code_caption": [],
        "code_body": "if expr1 # 如果 expr1 为真（返回值为0) then # 那么 commands1 # 执行语句块 commands1 elif expr2 # 若 expr1 不真，而 expr2 为真 then # 那么 commands2 # 执行语句块 commands2 ... ... # 可以有多个 elif 语句 else # else 最多只能有一个 commands4 fi # if 语句必须以单词 fi 终止",
        "guess_lang": "txt",
        "bbox": [
            144,
            653,
            853,
            839
        ],
        "page_idx": 36
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "$\\spadesuit$ elif可以有任意多个（o个或多个)",
            "$\\bullet$ else最多只能有一个 (o个或1个) ",
            "$\\bullet$ if 语句必须以fi表示结束",
            "exprx通常为条件测试表达式；也可以是多个命令，以最后一个命令的退出状态为条件值。",
            "$\\cdot$ commands为可执行语句块，如果为空，需使用shell提供的空命令“：”，即冒号。该命令不做任何事情，只返回一个退出状态0",
            "$\\bullet$ if语句可以嵌套使用"
        ],
        "bbox": [
            166,
            91,
            690,
            287
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "case 结构适合取值确定的多种情况的判断，但是也支持带通配符的模糊判断。",
        "bbox": [
            144,
            395,
            746,
            411
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "case语法格式",
        "text_level": 1,
        "bbox": [
            146,
            436,
            324,
            458
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "Shell case 语句为多选择语句。可以用 case 语句匹配一个值与一个模式，如果匹配成功，执行相匹配的命令。case 语句格式如下：",
        "bbox": [
            144,
            502,
            836,
            536
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "case 值 in ",
        "bbox": [
            146,
            554,
            230,
            568
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "模式 1)",
        "bbox": [
            146,
            586,
            206,
            601
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "command1 ",
        "bbox": [
            164,
            619,
            262,
            633
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "command2 ",
        "bbox": [
            164,
            652,
            263,
            665
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            690,
            184,
            699
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "commandN ",
        "bbox": [
            164,
            717,
            265,
            731
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            753,
            179,
            764
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "模式 2）",
        "bbox": [
            146,
            783,
            206,
            797
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "command1 ",
        "bbox": [
            164,
            816,
            262,
            829
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "command2 ",
        "bbox": [
            164,
            848,
            263,
            863
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            887,
            184,
            896
        ],
        "page_idx": 37
    },
    {
        "type": "text",
        "text": "commandN ",
        "bbox": [
            166,
            93,
            265,
            105
        ],
        "page_idx": 38
    },
    {
        "type": "text",
        "text": "esac ",
        "bbox": [
            147,
            160,
            189,
            171
        ],
        "page_idx": 38
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            " case 之后是取值，所以变量名之前不要忘记了$",
            "取值后面必须为单词in ",
            " 每一模式必须以右小括号) 结束",
            "取值可以为变量或常数",
            "匹配发现取值符合某一模式后，其间所有命令开始执行直至双分 ;; 号结束，表示break",
            "执行完匹配模式相应命令后不再继续其他模式",
            " 如果无一匹配模式，使用星号* 捕获该值，再执行后面的命令",
            "需要一个 esac（就是 case 反过来）作为结束标记"
        ],
        "bbox": [
            174,
            224,
            847,
            488
        ],
        "page_idx": 38
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "$\\cdot$ 表达式expr按顺序匹配每个模式，一旦有一个模式匹配成功，则执行该模式后面的所有命令，然后退出case。",
            "$\\bullet$ 如果expr 没有找到匹配的模式，则执行缺省值“*）”后面的命令块(类似于if 中的else); \"*)”可以不出现。",
            "$\\bullet$ 所给的匹配模式pattern中可以含有通配符和“」” ",
            "$\\bullet$ 每个命令块的最后必须有一个双分号，可以独占一行，或放在最后一个命令的后面。"
        ],
        "bbox": [
            203,
            527,
            690,
            680
        ],
        "page_idx": 38
    },
    {
        "type": "text",
        "text": "for 循环一般格式为：",
        "text_level": 1,
        "bbox": [
            144,
            731,
            396,
            753
        ],
        "page_idx": 38
    },
    {
        "type": "text",
        "text": "for var in item1 item2 ... itemN ",
        "bbox": [
            144,
            797,
            405,
            810
        ],
        "page_idx": 38
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            147,
            831,
            171,
            843
        ],
        "page_idx": 38
    },
    {
        "type": "text",
        "text": "command1 ",
        "bbox": [
            164,
            864,
            260,
            876
        ],
        "page_idx": 38
    },
    {
        "type": "text",
        "text": "command2 ",
        "bbox": [
            164,
            93,
            263,
            105
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            131,
            184,
            141
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "commandN ",
        "bbox": [
            164,
            159,
            265,
            172
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            147,
            192,
            194,
            205
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "上述for 循环中，in 之后是取值列表，逐个赋值给var变量，每次赋值就进行一次循环。这种循环类似于一些高级语言中的for each 循环结构。",
        "bbox": [
            144,
            256,
            838,
            292
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "列表 list 可以是命令替换、变量名替换、字符串和文件名列表 ( 可包含通配符 )，每个列表",
        "bbox": [
            144,
            307,
            850,
            324
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "项 以 空 格 间 隔 ",
        "bbox": [
            146,
            326,
            850,
            342
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "for 循 环 执 行 的 次 数 取 决 于 列 表 list 中 单 词 的 个 数",
        "bbox": [
            164,
            344,
            850,
            361
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "可 以 省 略 in list ， 省 略 时 相 当 于 in \"$@\"",
        "bbox": [
            188,
            363,
            850,
            380
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "另外，在 for 循环结构中，可以使用双小括号形式。",
        "bbox": [
            144,
            414,
            544,
            432
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "for $( ( \\mathrm { i } { = } 0 ; \\mathrm { i } { < } 1 0 0 ; \\mathrm { i } { + } + ) )$ ",
        "bbox": [
            144,
            448,
            305,
            463
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "do ",
        "bbox": [
            146,
            482,
            173,
            494
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "",
        "bbox": [
            164,
            520,
            184,
            527
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            146,
            546,
            194,
            560
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "break [n] ",
        "bbox": [
            146,
            579,
            225,
            595
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "用 于 强 行 退 出 当 前 循 环 。",
        "bbox": [
            144,
            612,
            840,
            627
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "如果是嵌套循环，则 break 命令后面可以跟一数字 n，表示退出第 n 重循环（最里面的为",
        "bbox": [
            144,
            630,
            847,
            646
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "第 重 循 环 ） 。",
        "bbox": [
            146,
            649,
            840,
            665
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "continue ",
        "bbox": [
            146,
            669,
            847,
            683
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "用 于 忽 略 本 次 循 环 的 剩 余 部 分 ， 回 到 循 环 的 顶 部 ， 继 续 下 一 次 循 环 。",
        "bbox": [
            144,
            686,
            838,
            702
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "如果是嵌套循环，continue 命令后面也可跟一数字 n，表示回到第 n 重循环的顶部",
        "bbox": [
            149,
            705,
            798,
            721
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "注意跟 case 的区别，for 之后是变量名，所以不要加$。",
        "bbox": [
            144,
            737,
            579,
            753
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "while 循环用于不断执行一系列命令，也用于从输入文件中读取数据；命令通常为测试条件。",
        "bbox": [
            144,
            770,
            847,
            804
        ],
        "page_idx": 39
    },
    {
        "type": "text",
        "text": "while 循环结构的语法格式为：",
        "text_level": 1,
        "bbox": [
            144,
            99,
            509,
            122
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "while cond_cmd ",
        "bbox": [
            144,
            166,
            285,
            181
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "do ",
        "bbox": [
            146,
            200,
            173,
            212
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "command ",
        "bbox": [
            164,
            231,
            253,
            244
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            146,
            265,
            193,
            277
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "while循环需要弄清楚的是条件命令执行成功的时候做循环，直到条件命令执行不成功，则退出循环。",
        "bbox": [
            144,
            330,
            836,
            363
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "2.3 无限循环",
        "text_level": 1,
        "bbox": [
            146,
            381,
            252,
            395
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "while : ",
        "bbox": [
            146,
            414,
            205,
            428
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "do ",
        "bbox": [
            146,
            448,
            173,
            460
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "command ",
        "bbox": [
            164,
            480,
            253,
            493
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            146,
            513,
            193,
            526
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "或者",
        "bbox": [
            146,
            577,
            186,
            592
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "while true ",
        "bbox": [
            146,
            611,
            233,
            624
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "do ",
        "bbox": [
            146,
            644,
            173,
            656
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "command ",
        "bbox": [
            164,
            677,
            253,
            690
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            146,
            709,
            193,
            722
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "或者",
        "bbox": [
            146,
            775,
            186,
            789
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "for (( ; ; )) ",
        "bbox": [
            146,
            807,
            223,
            822
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "until 循环执行一系列命令直至条件为真时停止。 until 循环与while 循环在处理方式上刚好相反。 一般 while 循环优于until 循环，但在某些时候—也只是极少数情况下，until 循环更加有用。",
        "bbox": [
            144,
            840,
            848,
            892
        ],
        "page_idx": 40
    },
    {
        "type": "text",
        "text": "until 语法格式: ",
        "bbox": [
            146,
            93,
            268,
            109
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "until cond_cmd ",
        "bbox": [
            146,
            126,
            277,
            142
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "do ",
        "bbox": [
            147,
            159,
            173,
            172
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "command ",
        "bbox": [
            164,
            192,
            253,
            205
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            147,
            225,
            194,
            237
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "条件可为任意测试条件，测试发生在循环末尾，因此循环至少执行一次，请注意这一点。",
        "bbox": [
            144,
            290,
            828,
            306
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "until false; do ",
        "bbox": [
            146,
            323,
            263,
            338
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "commands ",
        "bbox": [
            164,
            357,
            262,
            370
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "[ condition ] && break # 条件满足时退出循环 ",
        "bbox": [
            164,
            388,
            537,
            404
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            146,
            422,
            194,
            435
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "一 般 地 ， 使 用 while 循 环 配 合 case 实 现",
        "bbox": [
            144,
            454,
            848,
            469
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "后台执行循环（done &",
        "text_level": 1,
        "bbox": [
            146,
            505,
            336,
            521
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "Bash 提 供 了 专 门 的 select 循 环",
        "bbox": [
            144,
            537,
            848,
            554
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "select 循 环 主 要 用 于 创 建 菜 单",
        "bbox": [
            146,
            556,
            848,
            571
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "select 是 个 无 限 循 环 ",
        "bbox": [
            146,
            574,
            848,
            590
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "通 常 要 配 合 case 语 句 处 理 不 同 的 选 单 及 退 出",
        "bbox": [
            146,
            593,
            848,
            609
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "select 循 环 的 退 出",
        "bbox": [
            146,
            612,
            848,
            627
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "按 $\\mathsf { c t r } \\mathsf { l } { + } \\mathsf { c }$ 退 出 循 环 ",
        "bbox": [
            146,
            630,
            848,
            646
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "在 循 环 体 内 用 break 命 令 退 出 循 环",
        "bbox": [
            146,
            648,
            848,
            665
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "或 用 exit 命 令 终 止 脚 本",
        "bbox": [
            146,
            667,
            848,
            683
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "#!/bin/bash ",
        "bbox": [
            146,
            686,
            245,
            701
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "## filename: what-lang-do-you-like_while.sh ",
        "bbox": [
            146,
            703,
            848,
            721
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "while ",
        "bbox": [
            146,
            722,
            848,
            738
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "do ",
        "bbox": [
            146,
            741,
            173,
            756
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "echo \"====== Scripting Language ======\" ",
        "bbox": [
            268,
            760,
            848,
            777
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "echo \"1) bash\" ",
        "bbox": [
            443,
            778,
            848,
            794
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "echo \"2) perl\" ",
        "bbox": [
            443,
            797,
            848,
            813
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "echo \"3) python\" ",
        "bbox": [
            433,
            816,
            848,
            832
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "echo \"4) ruby\" ",
        "bbox": [
            443,
            835,
            848,
            850
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "echo \"5) (Quit) 1 ",
        "bbox": [
            381,
            853,
            848,
            869
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "read -p \"What is your preferred scripting language? \" lang ",
        "bbox": [
            189,
            871,
            848,
            888
        ],
        "page_idx": 41
    },
    {
        "type": "text",
        "text": "case $lang in ",
        "bbox": [
            447,
            891,
            848,
            906
        ],
        "page_idx": 41
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "1|bash) echo \"You selected bash\" ",
            "2|perl) echo \"You selected perl\" ",
            "3|python) echo \"You selected python\";; ",
            "4|ruby) echo \"You selected ruby\" ;; ",
            "5|quit) break ;; "
        ],
        "bbox": [
            164,
            91,
            853,
            183
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "esac ",
        "bbox": [
            808,
            187,
            850,
            199
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "done ",
        "bbox": [
            144,
            205,
            194,
            219
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "select 语法",
        "bbox": [
            144,
            223,
            238,
            239
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "按 数 值 顺 序 排 列 的 菜 单 项 （ list item ） 会 显 示 到 标 准 错 误",
        "bbox": [
            144,
            254,
            853,
            272
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "菜 单 项 的 间 隔 符 由 环 境 变 量 IFS 决 定",
        "bbox": [
            147,
            274,
            850,
            290
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "用 于 引 导 用 户 输 入 的 提 示 信 息 存 放 在 环 境 变 量 PS3 中",
        "bbox": [
            147,
            292,
            850,
            307
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "用 户 输 入 的 值 会 被 存 储 在 内 置 变 量 RELAY 中",
        "bbox": [
            147,
            311,
            850,
            326
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "用 户 直 接 输 入 回 车 将 重 新 显 示 菜 单",
        "bbox": [
            147,
            330,
            850,
            344
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "与 for 循 环 类 似 ， 省 略 in list 时 等 价 于 in “$*”",
        "bbox": [
            147,
            348,
            850,
            363
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "select variable in list ",
        "bbox": [
            147,
            367,
            850,
            382
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "do # 循 环 开 始 的 标 志",
        "bbox": [
            147,
            385,
            850,
            401
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "commands # 循 环 变 量 每 取 一 次 值 ， 循 环 体 就 执 行 一 遍",
        "bbox": [
            147,
            403,
            850,
            420
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "done # 循 环 结 束 的 标 志",
        "bbox": [
            147,
            423,
            850,
            438
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "参数处理",
        "bbox": [
            147,
            441,
            221,
            456
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "在 脚 本 中 经 常 使 用 流 程 控 制 处 理 位 置 参 数",
        "bbox": [
            144,
            473,
            853,
            489
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "循 环 结 构 while for",
        "bbox": [
            147,
            492,
            850,
            508
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "多 分 支 结 构 case",
        "bbox": [
            147,
            510,
            850,
            526
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "在 脚 本 中 经 常 使 用 如 下 命 令 配 合 位 置 参 数 处 理",
        "bbox": [
            147,
            529,
            850,
            545
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "shift ",
        "bbox": [
            147,
            548,
            189,
            563
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "getopts ",
        "bbox": [
            147,
            568,
            215,
            583
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "mybackup -z -c /etc/mybackup.conf -r -v ./foo.txt ./mydir ",
        "bbox": [
            144,
            602,
            853,
            620
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "-z 是 个 选 项 （ option ） ， 以 减 号 开 始 的 单 字 符",
        "bbox": [
            147,
            621,
            850,
            638
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "-c 也是个选项，/etc/mybackup.conf 是该选项的附加参数（additional argument ）",
        "bbox": [
            147,
            640,
            838,
            657
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "-r 和 -v 也 是 选 项 ， 且 不 带 附 加 参 数",
        "bbox": [
            147,
            659,
            850,
            675
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "./foo.txt 和 ./mydir 是脚本的处理对象，他们是不与任何选项相关的参数，在 POSIX®标",
        "bbox": [
            147,
            677,
            850,
            694
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "准中称其为“操作 对象/数”（operands）",
        "bbox": [
            147,
            696,
            477,
            713
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "getopts OPTSTRING VARNAME [ARGS...] ",
        "bbox": [
            144,
            795,
            850,
            810
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "OPTSTRING ",
        "bbox": [
            147,
            813,
            248,
            828
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "是 由 若 干 有 效 的 选 项 标 识 符 组 成 的 选 项 字 符 串",
        "bbox": [
            144,
            831,
            853,
            847
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "若 某 选 项 标 识 符 后 有 冒 号 ， 则 表 示 此 选 项 有 附 加 参 数",
        "bbox": [
            147,
            850,
            850,
            866
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "若 整 个 字 符 串 前 有 冒 号 ， 将 使 用 “ 安 静 ” 的 错 误 模 式",
        "bbox": [
            147,
            869,
            850,
            884
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "VARNAME ： 每 次 匹 配 成 功 的 选 项 保 存 在 变 量 中",
        "bbox": [
            147,
            887,
            850,
            902
        ],
        "page_idx": 42
    },
    {
        "type": "text",
        "text": "ARGS 参 数 列 表 ， 省 略 时 为 ” $@”",
        "bbox": [
            144,
            91,
            853,
            108
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "getopts c:zrv opt ",
        "bbox": [
            146,
            112,
            852,
            128
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "getopts :c:zrv opt ",
        "bbox": [
            147,
            131,
            850,
            146
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "通常需要以循环的方式执行多次 getopts 来解析位置参数中的选项以及可能存在的选项附",
        "bbox": [
            144,
            148,
            850,
            164
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "加 参 数",
        "bbox": [
            146,
            167,
            850,
            183
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "每 次 调 用 getopts ， 将 会 处 理 参 数 列 表 中 的 “ 下 一 个 ” 选 项",
        "bbox": [
            144,
            185,
            850,
            202
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "将 选 项 存 储 在 VARNAME 变 量 中",
        "bbox": [
            146,
            204,
            850,
            219
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "将 此 选 项 对 应 的 附 加 参 数 存 储 在 环 境 变 量 OPTARG 中",
        "bbox": [
            144,
            223,
            850,
            239
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "对环境变量OPTIND进行自增操作，使 $OPTIND 总是指向原始参数列表中“下一个”要",
        "bbox": [
            144,
            241,
            850,
            256
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "处 理 的 元 素 位 置",
        "bbox": [
            146,
            260,
            850,
            275
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "若$VARNAME 与$OPTSTRING 的所有选项均不匹配，则做“invalid option”的错误设置",
        "bbox": [
            144,
            278,
            850,
            294
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "若 某 选 项 的 参 数 不 存 在 ， 则 做 “ required argument not found” 的 错 误 设 置",
        "bbox": [
            144,
            297,
            850,
            313
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "冗 余 (Verbose) 模 式 （ OPTSTRING 不 以 : 开 头 ）",
        "bbox": [
            144,
            315,
            850,
            332
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "“invalid option” ",
        "bbox": [
            146,
            334,
            850,
            350
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "VARNAME=“?” unset OPTARG ",
        "bbox": [
            146,
            351,
            850,
            368
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "“required argument not found” ",
        "bbox": [
            147,
            370,
            850,
            386
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "VARNAM $\\bar { \\cdot } = \" ? \\prime$ unset OPTARG 并 输 出 错 误 信 息",
        "bbox": [
            144,
            390,
            850,
            405
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "安 静 (Silent) 模 式 （ OPTSTRING 以 : 开 头 ）",
        "bbox": [
            146,
            407,
            850,
            424
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "“invalid option” ",
        "bbox": [
            147,
            426,
            850,
            443
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "VARNAME $: = \" ? \"$ OPTARG=‘ 无 效 的 选 项 字 符 ，",
        "bbox": [
            144,
            445,
            850,
            461
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "“required argument not found” ",
        "bbox": [
            147,
            464,
            850,
            480
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "VARNAME=“:” ; OPTARG=‘ 与 参 数 对 应 的 选 项 字 符",
        "bbox": [
            144,
            482,
            850,
            497
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "函数",
        "text_level": 1,
        "bbox": [
            146,
            519,
            188,
            535
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "为 了 避 免 大 型 脚 本 变 得 复 杂 、 晦 涩 而 使 用 函 数",
        "bbox": [
            144,
            551,
            850,
            568
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "将 大 型 脚 本 代 码 分 割 成 小 块 ， 将 这 些 被 命 名 的 代 码 块 称 为 函 数",
        "bbox": [
            144,
            570,
            850,
            586
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "一 个 函 数 就 是 一 个 子 程 序 ， 用 于 完 成 特 定 的 任 务",
        "bbox": [
            144,
            589,
            850,
            605
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "如 ： 添 加 一 个 用 户 、 判 断 用 户 是 否 为 管 理 员 等",
        "bbox": [
            144,
            607,
            850,
            623
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "函 数 定 义 之 后 可 以 被 使 用 它 的 主 程 序 调 用",
        "bbox": [
            144,
            626,
            850,
            642
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "调 用 函 数 的 方 法 与 执 行 Shell 命 令 无 异",
        "bbox": [
            144,
            644,
            850,
            659
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "可 以 在 Shell 脚 本 中 调 用 （ 函 数 需 先 定 义 而 后 调 用 ）",
        "bbox": [
            144,
            663,
            850,
            678
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "在 命 令 行 上 直 接 调 用 （ 定 义 函 数 的 文 件 需 先 加 载 ）",
        "bbox": [
            144,
            682,
            850,
            697
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "简 化 程 序 代 码 ， 实 现 代 码 重 用",
        "bbox": [
            144,
            700,
            850,
            715
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "实现一次定义多次调用。如：is_root_user（）函数可以由不同的 shell脚本重复使用。",
        "bbox": [
            144,
            719,
            850,
            734
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "实 现 结 构 化 编 程",
        "bbox": [
            144,
            737,
            850,
            753
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "使 脚 本 内 容 更 加 简 洁 ， 增 强 程 序 的 易 读 性",
        "bbox": [
            144,
            755,
            850,
            771
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "提 高 执 行 效 率",
        "bbox": [
            144,
            774,
            850,
            790
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "将 常 用 的 功 能 定 义 为 多 个 函 数 并 将 其 保 存 在 一 个 文 件 中",
        "bbox": [
            144,
            791,
            850,
            809
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "类 似 其 他 语 言 的 66 模 块 ” 文 件",
        "bbox": [
            144,
            810,
            850,
            827
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "在 ~/bashrc 或 命 令 行 上 使 用 source 命 令 调 用 这 个 文 件",
        "bbox": [
            144,
            829,
            850,
            845
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "此 文 件 中 定 义 的 多 个 函 数 一 次 性 地 调 入 内 存 ， 从 而 加 快 运 行 速 度",
        "bbox": [
            144,
            848,
            850,
            864
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "function 函 数 名 { ",
        "bbox": [
            144,
            866,
            850,
            883
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "commands ",
        "bbox": [
            752,
            887,
            850,
            900
        ],
        "page_idx": 43
    },
    {
        "type": "text",
        "text": "} ",
        "bbox": [
            146,
            93,
            159,
            108
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 的 存 储",
        "bbox": [
            146,
            112,
            850,
            128
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 和 调 用 它 的 主 程 序 保 存 在 同 一 个 文 件 中",
        "bbox": [
            147,
            130,
            848,
            145
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 的 定 义 必 须 出 现 在 调 用 之 前",
        "bbox": [
            147,
            148,
            848,
            164
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 和 调 用 它 的 主 程 序 保 存 在 不 同 的 文 件 中",
        "bbox": [
            147,
            167,
            848,
            183
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "保 存 函 数 的 文 件 必 须 先 使 用 source 命 令 执 行 ， 之 后 才 能 调 用 其 中 的 函 数",
        "bbox": [
            147,
            186,
            848,
            202
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 的 显 示",
        "bbox": [
            147,
            205,
            848,
            219
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "显 示 当 前 Shell 可 见 的 所 有 函 数 名",
        "bbox": [
            147,
            223,
            848,
            239
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "$\\$ 1$ declare -F ",
        "bbox": [
            147,
            243,
            848,
            256
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "显 示 当 前 Shell 可 见 的 所 有 （ 指 定 ） 的 函 数 定 义",
        "bbox": [
            147,
            260,
            848,
            275
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "$\\$ 1$ declare -f ",
        "bbox": [
            147,
            279,
            848,
            293
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "$\\$ 1$ declare -f <functionName> ",
        "bbox": [
            147,
            297,
            848,
            312
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "参 数 (Arguments)",
        "bbox": [
            147,
            315,
            848,
            331
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "调 用 函 数 时 ， 使 用 位 置 参 数 的 形 式 为 函 数 传 递 参 数",
        "bbox": [
            147,
            334,
            848,
            349
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 内 的 $\\$ 1-\\$ 12$ $\\$ \\star$ 和機 $\\$ 0$ 表 示 其 接 收 的 参 数",
        "bbox": [
            147,
            353,
            848,
            368
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 调 用 结 束 后 位 置 参 数 $\\$ 1-\\$ 12$ 、 $\\$ \\star$ 和 $\\$ 0$ 将 被 重 置 为 调 用 函 数 之 前 的 值",
        "bbox": [
            147,
            370,
            848,
            386
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "在 主 程 序 和 函 数 中 ， $\\$ 0$ 始 终 代 表 脚 本 名",
        "bbox": [
            147,
            390,
            848,
            405
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "变 量 (Variables) ",
        "bbox": [
            147,
            407,
            848,
            423
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 内 使 用 local 声 明 的 变 量 是 局 部 （ Local ） 变 量",
        "bbox": [
            147,
            426,
            848,
            442
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "局 部 变 量 的 作 用 域 是 当 前 函 数 以 及 其 调 用 的 所 有 函 数",
        "bbox": [
            147,
            445,
            848,
            460
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 内 未 使 用 local 声 明 的 变 量 是 全 局 （ Global ） 变 量",
        "bbox": [
            147,
            464,
            848,
            479
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "即 主 程 序 和 函 数 中 的 同 名 变 量 是 一 个 变 量 （ 地 址 一 致 ）",
        "bbox": [
            147,
            482,
            848,
            497
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "当 函 数 的 最 后 一 条 命 令 执 行 结 束 函 数 即 结 束",
        "bbox": [
            147,
            501,
            848,
            516
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 的 返 回 值 就 是 最 后 一 条 命 令 的 退 出 码",
        "bbox": [
            147,
            520,
            848,
            533
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "其 返 回 值 被 保 存 在 系 统 变 量 $\\$ 7$ 中",
        "bbox": [
            147,
            538,
            848,
            552
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "可 以 使 用 return 或 exit 显 式 地 结 束 函 数",
        "bbox": [
            147,
            557,
            848,
            571
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "return [N]",
        "bbox": [
            147,
            576,
            848,
            590
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "return 将 结 束 函 数 的 执 行",
        "bbox": [
            147,
            594,
            848,
            609
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "可 以 使 用 N 指 定 函 数 返 回 值",
        "bbox": [
            147,
            612,
            848,
            627
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "exit [N]",
        "bbox": [
            147,
            632,
            848,
            646
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "exit 将 中 断 当 前 函 数 及 当 前 Shell 的 执 行",
        "bbox": [
            147,
            650,
            848,
            664
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "可 以 使 用 N 指 定 返 回 值",
        "bbox": [
            147,
            668,
            848,
            683
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "使 用 全 局 变 量 引 用 函 数 的 值 不 利 于 结 构 化 编 程",
        "bbox": [
            147,
            686,
            848,
            701
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "使 用 return 或 exit 只 能 返 回 整 数 值",
        "bbox": [
            147,
            705,
            848,
            720
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "使 用 标 准 输 出 实 现 函 数 的 返 回 值",
        "bbox": [
            147,
            722,
            848,
            738
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "是 一 种 通 用 的 方 法 ， 既 能 返 回 整 数 又 能 返 回 字 符 串",
        "bbox": [
            147,
            741,
            848,
            757
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "函 数 结 束 前 使 用 echo 命 令 将 结 果 显 示 到 标 准 输 出",
        "bbox": [
            147,
            760,
            848,
            775
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "调用函数时使用如下的格式将函数的输出结果存到变量 RES 中，之后便可使用变量 $\\$ 123$ ",
        "bbox": [
            147,
            778,
            848,
            793
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "的 值 （ 或 输 出 、 或 执 行 测 试 、 或 进 一 步 处 理 等 ）",
        "bbox": [
            147,
            797,
            838,
            813
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "$R E S { = } \\$ $ (functionName) ",
        "bbox": [
            147,
            816,
            332,
            831
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "echo ",
        "bbox": [
            147,
            835,
            191,
            848
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "$RES ",
        "bbox": [
            803,
            835,
            848,
            848
        ],
        "page_idx": 44
    },
    {
        "type": "text",
        "text": "Ken Thompson 的 sh 是第一种 Unix Shell，Windows Explorer 是一个典型的图形界面Shell。",
        "bbox": [
            144,
            143,
            848,
            179
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "当命令不在命令行中执行，而是从一个文件中执行时，该文件就称为shell脚本",
        "bbox": [
            144,
            199,
            761,
            216
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Shell 脚本是纯文本文件",
        "bbox": [
            147,
            219,
            336,
            235
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": ".sh 为文件后缀名",
        "bbox": [
            149,
            237,
            284,
            253
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "以行为单位，执行脚本的时候会分解成一行一行依次执行",
        "bbox": [
            144,
            292,
            593,
            309
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Shell 是一种功能强大的解释型语言",
        "bbox": [
            147,
            311,
            423,
            326
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "通常用",
        "bbox": [
            147,
            330,
            203,
            344
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "变量、数组、输入输出",
        "bbox": [
            149,
            348,
            327,
            363
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "控制结构",
        "bbox": [
            149,
            367,
            221,
            382
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Shell脚本的建立",
        "bbox": [
            149,
            386,
            282,
            401
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Vim script ",
        "bbox": [
            149,
            404,
            233,
            420
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Chomod +x(exectue) script-file ",
        "bbox": [
            149,
            422,
            401,
            439
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "以#！开头：通知系统用何解释器执行此脚本",
        "bbox": [
            149,
            441,
            497,
            457
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "#!/bin/bash ",
        "bbox": [
            149,
            460,
            245,
            473
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "#脚本名称、脚本功能",
        "bbox": [
            149,
            478,
            321,
            493
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "在 bash 调用脚本时使用参数",
        "bbox": [
            149,
            497,
            374,
            512
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "$\\$ 1$ bash [-x] [-n] [-v] name ",
        "bbox": [
            152,
            514,
            357,
            531
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "在脚本中",
        "bbox": [
            149,
            533,
            221,
            549
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Sh-x 脚本名",
        "bbox": [
            149,
            552,
            242,
            567
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Shell 的功能",
        "bbox": [
            149,
            571,
            247,
            586
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "各种管理和监视命令的使用",
        "bbox": [
            149,
            589,
            361,
            605
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Ebal对参数进行两次扫描和替换 ",
        "bbox": [
            149,
            608,
            401,
            623
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "将所有的参数链接诚意表达式，ving计算或执行限该白澳大使】参数中的任何变量的将被",
        "bbox": [
            147,
            626,
            848,
            642
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "展开 ",
        "bbox": [
            149,
            645,
            186,
            659
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "各种文本文件工具的使用",
        "bbox": [
            149,
            664,
            344,
            678
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "变量和表达式",
        "bbox": [
            149,
            682,
            255,
            697
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "变量替换扩展",
        "bbox": [
            149,
            701,
            255,
            715
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "变量测试 ",
        "bbox": [
            149,
            737,
            221,
            753
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "变量的字符串操作",
        "bbox": [
            149,
            756,
            292,
            771
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "计数、截取 ",
        "bbox": [
            149,
            775,
            240,
            789
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "变量的间接引用",
        "bbox": [
            149,
            793,
            273,
            808
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "通过str2的值来引用str1的值",
        "bbox": [
            149,
            812,
            386,
            827
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "位置参数变量",
        "bbox": [
            149,
            831,
            255,
            845
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Shit 参数 【0】",
        "bbox": [
            149,
            848,
            260,
            864
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "$\\$ 7$ ",
        "bbox": [
            149,
            868,
            169,
            881
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "Exit ",
        "bbox": [
            149,
            887,
            181,
            900
        ],
        "page_idx": 45
    },
    {
        "type": "text",
        "text": "命令行参数相关 ",
        "bbox": [
            147,
            111,
            275,
            127
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "0 执行正确 ",
        "bbox": [
            147,
            130,
            236,
            145
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "1 通用错误",
        "bbox": [
            147,
            149,
            236,
            162
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "2 命令或脚本没有执行权限",
        "bbox": [
            147,
            168,
            359,
            181
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "127 命令没找到",
        "bbox": [
            147,
            186,
            273,
            200
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Chmod $+ x + w + r$ ",
        "bbox": [
            147,
            205,
            280,
            218
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Read从键盘输入内容为变量赋值",
        "bbox": [
            147,
            223,
            406,
            237
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Read ",
        "bbox": [
            147,
            242,
            191,
            255
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "结合不同的引号为变量赋值",
        "bbox": [
            147,
            260,
            361,
            275
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Readonly ",
        "bbox": [
            147,
            279,
            228,
            294
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "多行内容不能出现双引号，否则用转义字符\\“",
        "bbox": [
            152,
            297,
            505,
            312
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Head_file ",
        "bbox": [
            147,
            316,
            226,
            330
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "进程参数相关 ",
        "bbox": [
            147,
            334,
            255,
            349
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Printf ",
        "bbox": [
            147,
            353,
            198,
            366
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Let 不必架空客，否则加上反引号",
        "bbox": [
            147,
            370,
            413,
            386
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Expr 必须加空格",
        "bbox": [
            147,
            390,
            278,
            405
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "$[expression]/ ",
        "bbox": [
            147,
            409,
            268,
            424
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Eval newstr=\\$$ ",
        "bbox": [
            147,
            426,
            280,
            441
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "${var :-word}/${var:=word}/${var:?wor} ",
        "bbox": [
            147,
            445,
            470,
            461
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "数组变量",
        "bbox": [
            147,
            464,
            221,
            478
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "小标从0开始",
        "bbox": [
            147,
            482,
            255,
            495
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Declare variable $=$ value 用来声明变量",
        "bbox": [
            147,
            501,
            447,
            516
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Unset variable ",
        "bbox": [
            147,
            520,
            270,
            533
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Echo $variable echo ${variable} ",
        "bbox": [
            147,
            538,
            410,
            552
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "变量的数值计算",
        "bbox": [
            147,
            575,
            273,
            590
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Expr ",
        "bbox": [
            147,
            594,
            189,
            609
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "输入",
        "bbox": [
            147,
            612,
            186,
            627
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "变量名 ",
        "bbox": [
            147,
            631,
            201,
            645
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "输出",
        "bbox": [
            147,
            650,
            186,
            664
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Echo printf ",
        "bbox": [
            147,
            669,
            242,
            683
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "for variable in list ",
        "bbox": [
            147,
            687,
            295,
            700
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "每一次循环，依次把列表 list 中的一个值赋值给循环变量",
        "bbox": [
            147,
            705,
            586,
            720
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "使用字面字符串列表作为 wordlist",
        "bbox": [
            147,
            724,
            416,
            738
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "若列表项中包含空格必须使用引号括起来",
        "bbox": [
            147,
            741,
            468,
            757
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "While 循环 ",
        "bbox": [
            147,
            760,
            236,
            775
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "For 循环 ",
        "bbox": [
            147,
            778,
            216,
            793
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Until 循环 ",
        "bbox": [
            147,
            797,
            230,
            812
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Done&后台执行循环 ",
        "bbox": [
            147,
            816,
            314,
            831
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Tumx 可以在后台打开，不会因为 terminal 断开而断开连接",
        "bbox": [
            147,
            835,
            613,
            848
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "一般地使用while 循坏配合case实现",
        "bbox": [
            147,
            853,
            440,
            866
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "Base 提供 select 循环",
        "bbox": [
            147,
            872,
            319,
            885
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "按数值顺序排列的菜单项（list item）会显示到标准错误 ",
        "bbox": [
            147,
            890,
            588,
            904
        ],
        "page_idx": 46
    },
    {
        "type": "text",
        "text": "位置参数和控制参数",
        "text_level": 1,
        "bbox": [
            147,
            93,
            312,
            109
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Shell 的内置命令 getopts 可以识别所有常见的选项格式",
        "bbox": [
            144,
            130,
            584,
            147
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Gtopts OPTSTRING VARNAME [ARGS] ",
        "bbox": [
            146,
            148,
            458,
            165
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Optstirng ",
        "bbox": [
            147,
            167,
            231,
            183
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "是哦有若干有效的选项标识符组成的选项字符串",
        "bbox": [
            146,
            185,
            522,
            200
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "若某选项标识符后又冒号，则表示此选项又附加参数",
        "bbox": [
            146,
            204,
            557,
            219
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "若整个字符串前又冒号，将使用安静的错误模式",
        "bbox": [
            146,
            223,
            522,
            239
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Varnmae：每次匹配成功的选项保存在变量中",
        "bbox": [
            146,
            241,
            509,
            256
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "默认为$@ ",
        "bbox": [
            147,
            260,
            230,
            275
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Getopts 不能解析 GNU -style 长参数",
        "bbox": [
            146,
            279,
            438,
            294
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Getopts 从不改变原始位置参数，若希望移动位置参数，需手工执行shift",
        "bbox": [
            146,
            297,
            721,
            313
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Getopts 会自动对变量 optnd",
        "bbox": [
            146,
            316,
            379,
            332
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "合理使用shell函数",
        "bbox": [
            147,
            334,
            302,
            349
        ],
        "page_idx": 47
    },
    {
        "type": "list",
        "sub_type": "text",
        "list_items": [
            "1、简化程序代码，实现代码重用",
            "2、实现结构化编程",
            "3、提高执行效率 "
        ],
        "bbox": [
            146,
            353,
            411,
            424
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Function commands ",
        "bbox": [
            146,
            445,
            319,
            460
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "参数",
        "bbox": [
            147,
            464,
            186,
            478
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "调用函数时，使用位置参数的形式位函数传递参数",
        "bbox": [
            146,
            482,
            539,
            498
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "函数内的 $\\$ 1-\\$ 12$ 都是位置参数",
        "bbox": [
            147,
            501,
            445,
            517
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Return 或者 exir 只能返回整数值",
        "bbox": [
            146,
            538,
            408,
            552
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "使用标准输出实现函数的返回值",
        "bbox": [
            146,
            556,
            398,
            571
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "函数结束前",
        "bbox": [
            147,
            575,
            238,
            590
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Sysinfo.sh ",
        "bbox": [
            147,
            594,
            235,
            609
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Sysinfo_ ",
        "bbox": [
            147,
            612,
            220,
            627
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "标准输入/输出设备",
        "bbox": [
            146,
            630,
            299,
            646
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Linux命令在执行时常常期望接收输入数据，命令执行后又期望将产生的数据结果输出。",
        "bbox": [
            144,
            648,
            836,
            665
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "Linux 的 大 部 分 命 令 都 具 有 标 准 的 输 入 / 输 出 设 备 端 口 。",
        "bbox": [
            144,
            668,
            838,
            684
        ],
        "page_idx": 47
    },
    {
        "type": "table",
        "img_path": "images/b7661213680e3ff117ddcc2c70c46427fd4ac9ca78bb4ddd9c953bfaac41201e.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>名称</td><td>文件描述符</td><td>含义</td><td>设备</td><td>说明</td></tr><tr><td>STDIN</td><td>0</td><td>标准输入</td><td>键盘</td><td>命令在执行时所要的输入通过它来取得</td></tr><tr><td>STDOUT</td><td>1</td><td>标准输出</td><td>显示器</td><td>命令执行后的输出结果从该端口送出</td></tr><tr><td>STDERR</td><td>2</td><td>标准错误</td><td>显示器</td><td>命令执行时的错误信息通过该端口送出</td></tr></table>",
        "bbox": [
            147,
            702,
            998,
            853
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "所谓重定向，就是不使用系统的标准输入端口、标准输出端口或标准错误端口，而进行重新的指定，所以重定向分为输出重定向、输入重定向和错误重定向。通常情况下重定向到",
        "bbox": [
            144,
            857,
            850,
            892
        ],
        "page_idx": 47
    },
    {
        "type": "text",
        "text": "个 文 件 。",
        "bbox": [
            144,
            93,
            840,
            109
        ],
        "page_idx": 48
    },
    {
        "type": "text",
        "text": "在Shell中，要实现重定向主要依靠重定向符实现，即 Shell是检查命令行中有无重定向符来 决 定 是 否 需 要 实 施 重 定 向 。",
        "bbox": [
            144,
            111,
            848,
            146
        ],
        "page_idx": 48
    },
    {
        "type": "table",
        "img_path": "images/ae8a233e1f7347f880789d75f607096032d0d4e3b8e13b814b8ce88f9fa05796.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>重定向符</td><td>说明</td></tr><tr><td>&lt;</td><td>输入重定向</td></tr><tr><td>&lt;&lt;!</td><td>输入重定向的特例,即HERE文件,通常用于Shell脚本中。其中“!”可以仅只要其没在……中出现过即可。</td></tr><tr><td>!</td><td></td></tr><tr><td>&gt;</td><td>覆盖式的输出重定向</td></tr><tr><td>&gt;&gt;</td><td>追加式的输出重定向</td></tr><tr><td>2&gt;</td><td>覆盖式的错误输出重定向</td></tr><tr><td>2&gt;&gt;</td><td>追加式的错误输出重定向</td></tr><tr><td>&amp;&gt;</td><td>同时实现输出重定向和错误重定向(覆盖式)</td></tr><tr><td colspan=\"2\">空 设 备 (/dev/null)</td></tr><tr><td colspan=\"2\">空 设 备 是 个 黑 洞,发 往 它 的 任 何 内 容 都 将 不 复 存 在</td></tr><tr><td colspan=\"2\">经常 用于 屏 蔽 命 令 的 输 出 或 错 误 输出,尤其用于 Shell 脚 本 中</td></tr><tr><td colspan=\"2\">空 设 备 使 用 举 例</td></tr><tr><td colspan=\"2\">屏蔽 命 令 的 输 出 和 错 误 输 出 /dev/null</td></tr><tr><td colspan=\"2\">$ myprogram &amp;&gt;/dev/null</td></tr><tr><td colspan=\"2\">$ myprogram &gt;/dev/null 2&gt;&amp;1</td></tr><tr><td colspan=\"2\">清 空 文 件 内 容</td></tr><tr><td colspan=\"2\">$ cp /dev/null myfile</td></tr><tr><td colspan=\"2\">$ &gt; myfile</td></tr><tr><td colspan=\"2\">命令替换</td></tr><tr><td colspan=\"2\">使用 命 令 的 输 出 ,常 用 于</td></tr><tr><td colspan=\"2\">在 文 本 中 嵌 入 命 令 的 执 行 结 果</td></tr><tr><td colspan=\"2\">命令 参 数 是 另 一 个 命 令 执 行 的 结 果</td></tr><tr><td colspan=\"2\">使 用 方 法</td></tr><tr><td colspan=\"2\">$(command) 或 `command`</td></tr><tr><td colspan=\"2\">cmd1 $(cmd2) 或 cmd1 `cmd2`</td></tr><tr><td colspan=\"2\">使 用 举 例</td></tr><tr><td colspan=\"2\">$ echo The present time is `date`</td></tr><tr><td colspan=\"2\">$ rpm -qi $(rpm -qf $(which date)) # 嵌 套</td></tr><tr><td colspan=\"2\">命令组合</td></tr></table>",
        "bbox": [
            147,
            165,
            1000,
            864
        ],
        "page_idx": 48
    },
    {
        "type": "text",
        "text": "命令行形式",
        "bbox": [
            157,
            872,
            252,
            889
        ],
        "page_idx": 48
    },
    {
        "type": "text",
        "text": "说明",
        "bbox": [
            502,
            872,
            542,
            888
        ],
        "page_idx": 48
    },
    {
        "type": "text",
        "text": "举例",
        "bbox": [
            885,
            872,
            924,
            888
        ],
        "page_idx": 48
    },
    {
        "type": "table",
        "img_path": "images/1b2f5d09e741800ebdacbd78c268f11db67f138c98b9c31c6dd02f44ada08cbf.jpg",
        "table_caption": [],
        "table_footnote": [],
        "table_body": "<table><tr><td>CMD1; CMD2</td><td>顺序执行若干命令</td><td>pwd;date;ls</td></tr><tr><td>CMD1 &amp;&amp; CMD2</td><td>当CMD1运行成功时才运行CMD2</td><td>gzip mylargef</td></tr><tr><td>CMD1 || CMD2</td><td>当CMD1运行失败时才运行CMD2</td><td>write osmonc\nmy.log</td></tr><tr><td>(CMDLIST)</td><td>在子Shell中执行命令序列</td><td>(date; who | v)</td></tr><tr><td>{CMDLIST}</td><td>在当前Shell中执行命令序列</td><td>{cd /home/jjh}</td></tr></table>",
        "bbox": [
            147,
            90,
            1000,
            284
        ],
        "page_idx": 49
    }
]