Shell中引用是用于去除某些字符的特殊含义, 而使其回归字面意思. 引用可以防止扩展(参数扩展,路径扩展等), 命令替换以及here-document的发生. 在Shell至少以下字符(字符后面括号中文字解释其用途)是特殊的, 所以如果想要这些字符的字面意思, 就需要引用: |(管道) &(后台执行) ;(命令分隔符) <和>(重定向) (和)(子进程) `(命令替换) $(变量/参数扩展) \(转义/行继续) "(引用) '(引用) <space>(参数分隔符) <tab>(参数分隔符) <newline>(行分隔符) 以下字符可能需要引用, 他们是否表示字面意思得看条件: * ? [ 这3个是glob模式匹配字符, 当模式匹配能够发生时, 这些字符将失去字面意思. 比如对命令echo ab* 若当前目录下存在ab开头的文件(或目录), 则该命令输出这些文件/目录的名称(所以*失去字面意思), 而当不存在此类文件或目录时, 该命令仅输出ab*(即*取字面意思). 对?和[也是一样的. % 对于支持作业控制shell实现(如csh,bash)而言, %后加数字表示指定的作业, 除此之外%表示百分号字符而已(字面意思) # 当其作为某命令行第一个非空字符出现时, 其表示注释(非字面意思), 否则取字面意思. = 当name=value出现在实际命令之前时, 其表示赋值(当赋值后无命令时, 该赋值将一直有效直到再次赋值或取消变量; 当赋值后有命令时, 该赋值仅对紧随命令有效, 比如n1=v1 ls中n1=v1仅在执行此条ls时有效), 其他情况下, 其表示等号. ~ 单独使用表示当前用户HOME目录, 当后面跟用户名时表示该用户HOME目录, 否则取字面意思. 引用的机制有: 使用转义符, 使用单引号, 使用双引号, here-document. 1 转义符(反斜杠\) 反斜杠使紧接其后的那个字符取字面意思, 当紧接字符本来就无特殊意义时, 该转义符被忽略. 唯一的例外是后接<newline>(即换行符). 当后面为换行符时, 表示行继续, 即紧接的行内容将加到当前命令行的末尾, 在对新的当前命令行进行符号分解之前, 换行符和反斜杠都将被删除. 由于换行符被删除, 所以该换行符将不能作为符号分隔符. 比如 echo abc\ def 实际的命令将是echo abcdef, 如果想要保证行继续前有空格分隔, 一般应当在\之前就添加空格. 2 单引号 所有在一对单引号中的字符都表现出字面意思. 只有单引号本身不可出现在一对单引号中. 3 双引号 在一对双引号中的大部分字符可以表现出字面意思, 除了以下: $ 该符号仍然可以用于执行参数扩展(即取参数值, 包含位置参数和正常参数), 命令替换(比如$(command)等, 表达式将被command的输出所替代), 以及算术表达式扩展($((expr)),该表达式将被expr的最终结果所替代) ` 反引号用于进行命令替换, `command`将被command的输出所替代. \ 该字符只有当其后跟着下列字符时, 其才具有转义字符的含义: $ ` " \ <newline> 此说明在双引号对中可以有双引号, 只要用\前置即可. 4 Here-document 重定向操作符<<和<<-允许将脚本中一系列行重定向到一个命令的某个文件描述符, 该一系列行将作为一个整体, 被称为here-document, 其格式为: [n] << word here-document delimiter 其中n表示要被重定向的那个文件描述符, 如果省略, 则默认是0, 表示标准输入. 如果word中的任何字符被引用, 则delimeter应是word的去引用版本, 且here-document中将不会有任何扩展发生. 否则, delimiter应与word相同, 且允许扩展(包含参数扩展, 命令替换和数学表达式扩展). 比如有 name=value 则对于 cat <<"EOF" name is $name EOF 其结果为name is $name 而对于 cat <<EOF name is $name EOF 其结果则为name is value here-document中的双引号将不具有引用的含义, 除非该双引号在$(), ``或 ${}中, 且该here-document允许这些扩展发生. 如果重定向符号是<<-, 则所有行中开始的<tab>序列都会被剔除. 如果<<和<<-都使用的话, 第一个出现的起作用. |
|