EKo*_*ons 14 shell special-characters quoting
许多问题,例如“如何键入双引号字符 (")?” 正在被问到,我们不想用相同的答案来扰乱我们的社区(输入时
\"好像不包含在's 中,"如果包含在's 中。)所以,问题就在这里。
您不能像普通字符那样在终端中输入特殊字符,例如此命令将失败:
echo Updates (11)
Run Code Online (Sandbox Code Playgroud)
那么,如何在终端中输入这些字符,就像它们是普通字符一样?
echo Updates (11)
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 32
这在很大程度上取决于外壳。有关详细信息,请查看您的 shell 手册。
另请注意,某些字符仅在某些上下文中是特殊的。例如,在大多数 shell 中,*并且?仅在列表上下文中是特殊的,在 POSIX 或类似 csh 的 shell 中,~仅在单词的开头或某些字符(如:. 同为=in zsh。在某些 shell 中,[只有在与].
在某些 shell 中,如bash或yash,特殊字符(如空白标记分隔符)也因区域设置而异。
引号操作符(删除这些字符的特殊含义)在不同的 shell 之间也有很大差异。
类似 Bourne 的 shell(即sh自 80 年代以来已知在某些系统或其他系统上调用的 shell)的摘要:
"'&|;()^`<>$、空格、换行符和制表符在不带引号的简单命令行中是特殊的。#(早期版本除外)在行首或未加引号的空格、制表符或&|()^<>;`.{并且}唯一的特殊之处在于它们是 shell 关键字(因此只有在命令位置的单词)。*?[作为通配符是特殊的,所以只在列表上下文中。在 的情况下[,它[...]是通配符,要么[或]只需要引用以删除特殊含义。=在将其视为赋值运算符的上下文中是特殊的。也就是说,在一个简单的命令中,对于所有不跟在参数后面的词(除了之后set -k)。\引用除换行符之外的所有特殊字符(\<newline>是一种将长逻辑行延续到下一个物理行的方法,以便删除该序列)。请注意,反引号会增加额外的复杂性,因为它们\首先用于转义结束反引号并帮助解析器。在双引号内,\只能用于转义自身,",$和`(\<newline>仍然是一个续行)。在 here-document 中,除了". \是对此处文档中的字符进行转义的唯一方法。"..."双引号转义除自身、\、$和 之外的所有字符`。'...' 单引号转义除自身之外的所有字符。POSIX shell 的行为与 Bourne shell 大致相似,不同之处在于:
ksh像 POSIX 一样,除了:
{string}如果 string 包含未加引号的,(或..在某些情况下和某些版本中)则是特殊的。$'...'复杂规则。在bash、zsh、mkshFreeBSD 和 busybox 中也可以找到该运算符(有一些变化)sh。ksh93也有一个$"..."引用操作符,"..."除了字符串需要本地化(可以配置为翻译成用户的语言)。mksh忽略$in $"..."。ksh93r,在交互式 shell 中ksh93使用-H/支持 csh 风格的历史扩展(默认情况下不启用),-o histexpand这使得^命令的开头和!特殊。!然后在某些上下文中是特殊的(后面不是空格或制表符,也不是在此处的文档中)并且不会被双引号转义。只有反斜杠(不在双引号内)和单引号转义它。bash喜欢ksh93但是:
bash,!有时也不特别,当后跟".zsh喜欢ksh93但是:
bashcsh 历史扩展相同的注意事项=作为单词的第一个字符(=ls扩展为/bin/ls)是特殊的。{并且}还可以在未分隔时打开和关闭命令组({echo text}如 Bourne's 之类的作品{ echo text;})。[单独之外,[即使没有用].extendedglob启用该选项后#,^和~是通配符。braceccl选项,{non-empty-string}很特别。$"..." 不支持。?跟随 a %(甚至引用或扩展)时并不特殊(以允许%?name工作规范)rcquotes选项(默认情况下未启用)允许在单引号''内输入单引号 à la rc(见下文)。yash就像POSIX不同的是。
brace-expand选项,实现 zsh 样式的大括号扩展。对于所有 shell,在某些特殊上下文中,引用的工作方式有所不同。我们已经在这里提到了文档和反引号,但[[...]]在 ksh 和其他一些 shell、POSIX $((...))、case构造中也有...
另请注意,当涉及扩展(使用双引号)或应用于此处的文档分隔符时,引用可能会产生其他副作用。它还禁用保留字并影响别名扩展。
在类似 Bourne 的 shell 中,!#$^&*?[(){}<>~;'"`|=、SPC、TAB、NEWLINE 和一些设置了第 8 位的字节是或可能是特殊的(至少在某些情况下)。
要删除特殊含义以便按字面意思对待它们,请使用引用。
用:
'...' 删除每个字符的特殊含义:
printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
single arguments (without the enclosing quotes) to `printf`'
Run Code Online (Sandbox Code Playgroud)
\ 仅删除一个字符的特殊含义:
printf '<%s>\n' foo bar\ baz #comment
Run Code Online (Sandbox Code Playgroud)
上面,只有以 a 开头的空格字符才按\字面传递给printf. 其他的被 shell 视为标记定界符。
用于"..."引用字符,同时仍然允许参数扩展($var, $#, ${foo#bar}...)、算术扩展($((1+1)),也在$[1+1]某些 shell 中)和命令替换($(...)或旧形式`...`。实际上,大多数时候,您确实希望将这些扩展放在里面在任何情况下都可以使用双引号。您可以使用\inside"..."删除仍然特殊的字符的特殊含义(但仅限于它们)。
如果字符串包含'字符,您仍然可以将其'...'用于其余部分,并使用其他可以引用'类似"'"or\'或(如果可用)的引用机制$'\'':
echo 'This is "tricky", isn'\''t it?'
Run Code Online (Sandbox Code Playgroud)
使用现代$(...)形式的命令替换。仅使用旧`...`版本与 Bourne shell 兼容,即非常旧的系统,并且仅用于变量赋值,如不使用:
echo "`echo "foo bar"`"
Run Code Online (Sandbox Code Playgroud)
这不适用于 Bourne shell 或 AT&T 版本的 ksh。或者:
echo "`echo \"foo bar\"`"
Run Code Online (Sandbox Code Playgroud)
这将适用于 Bourne 和 AT&T ksh,但不适用于yash(2020 年编辑:仅在 2.41 版及更早版本中,此后已在 2.42 /错误报告/提交中更改),但使用:
var=`echo "foo bar"`; echo "$var"
Run Code Online (Sandbox Code Playgroud)
这将适用于所有人。
用双引号可移植地嵌套它们也是不可能的,所以再次使用变量。还要注意特殊的反斜杠处理:
var=`printf '%s\n' '\\'`
Run Code Online (Sandbox Code Playgroud)
将仅在其中存储一个反斜杠$var,因为在反引号中有一个额外的反斜杠处理级别(for \、` 和$(以及"除了 in 引用时yash)),因此您需要
var=`printf '%s\n' '\\\\'`
Run Code Online (Sandbox Code Playgroud)
或者
var=`printf '%s\n' '\\\'
Run Code Online (Sandbox Code Playgroud)
反而。
csh 和 tcsh 具有明显不同的语法,尽管它们与 Bourne shell 仍有很多共同点,因为它们具有共同的传统。
"'&|;()^`<>$、空格、换行符和制表符在没有引用时在任何地方都是特殊的。#(csh 是#作为注释引导器引入的 shell ) 在脚本的开头或未加引号的空格、制表符或换行符之后是特殊的。*?[ 在列表上下文中作为通配符是特殊的{non-empty-string} 是特殊的(csh 是引入大括号扩展的外壳)。!并且^作为历史扩展的一部分是特殊的(再次是 csh 的发明),并且引用规则是特殊的。~ (波浪号扩展也是 csh 的发明)在某些情况下是特殊的。它们与 Bourne shell 相同,但行为不同。从语法的角度来看,tcsh 的行为类似于 csh,您会发现许多版本的 csh 都有令人讨厌的错误。获取最新版本的 tcsh 以获得大致可用的 csh 版本。
\转义除换行符之外的单个字符(与 Bourne shell 相同)。它是唯一可以转义的引用运算符!。\<newline>不会转义它,而是将它从命令分隔符转换为标记分隔符(如空格)"..."转义除自身、$、`、 换行符和之外的所有字符!。与 Bourne shell 相反,您不能使用\转义$和`内部"...",但您可以使用\转义!或换行符(但不能使用它本身,除非在 a!或换行符之前)。文字!是"\!"和文字\!是"\\!"。'...' 转义除自身!和换行符以外的所有字符。就像双引号一样,!换行符可以用反斜杠转义。`...`语法进行,很难可靠地使用。$var:q运营商可以帮助编写更可靠的代码包含变量。如果可以,请远离 csh。如果您不能使用:
!和换行符仍然需要一个\.\ 可以转义大多数字符"..."可以允许在其中进行一些扩展,但是如果它们嵌入换行符和/或反斜杠字符,那就很麻烦了,最好只使用单引号并$var:q用于变量扩展。如果要可靠地连接数组元素,则需要使用循环。rc 家庭rc是plan9shell 及其后代es,akanga并已移植到 Unix 和类 Unix 系统。这是一个具有更清晰和更好语法的外壳,如果我们不坚持使用类似 Bourne 的外壳来实现向后兼容性,那么每个人都会使用这种外壳。
rc/akanga#;&|^$=`'{}()<>, SPC, TAB 和 NEWLINE 在不引用时总是特殊的。*?[ 是通配符。'...'是唯一的引用运算符。一个litteral'写有''单引号作为内:
echo 'it''s so simple isn''t it?'
Run Code Online (Sandbox Code Playgroud)
eses可以被看作是一个实验基于壳rc。
虽然它有一些差异。这个 Q/A 的一个有趣之处在于\它也是一个引用运算符(它引用除换行符之外的所有特殊字符),也可用于引入转义序列,如\n换行符、\b反斜杠......
fish 是一个相对较新的人(大约 2005 年),主要用于交互式使用,并且与其他 shell 的语法也有很大不同。
"'\()$%{}^<>;&|不引用时总是特殊的(注意%(对于 pid 扩展)作为与其他 shell 的显着区别,`并不特殊)# (comment) 跟随未加引号的空格、制表符、换行符或 ;&|^<>*?(但不是[...])通配符\引用除换行符之外的单个特殊字符,但要注意它也可以作为 C 转义序列 ( \n, \b...) 介绍人使用。IOW,\n不是引用n而是换行符。"..."引用除自身以外的所有内容,$反斜杠和反斜杠可用于转义这些内容。\<newline>是 内的续行(已删除)"..."。'...'引用除自身和之外的所有内容\,您可以使用反斜杠来转义它们。使用 a 转义所有这些字符\,如下所示(不适用于换行符/回车符):
$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.
Run Code Online (Sandbox Code Playgroud)
将整个文本括在"s 中,如下所示:
$ var=variables;echo "Enclose text in \"s. You can also use $var in them. `echo Surprise!!!`"
Enclose text in "s. You can also use variables in them. Surprise!!!
Run Code Online (Sandbox Code Playgroud)
与双引号相同,但没有特殊标记。
$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
83881 次 |
| 最近记录: |