许多问题,例如“如何输入双引号字符(”)?正在被问到,我们不想用相同的答案来扰乱我们的社区(
\"
如果没有包含在'
s 中,则键入它,"
如果包含在'
s 中。)所以,问题就在这里。
您不能像普通字符一样在终端中输入特殊字符,例如此命令将失败:
echo Updates (11)
那么,如何在终端中像普通字符一样输入这些字符呢?
!#$^&*?[](){}<>~;'"\|<space><tab><newline>
答案1
这很大程度上取决于外壳。有关详细信息,请检查您的 shell 手册。
另请注意,某些字符仅在某些上下文中才特殊。例如,在大多数 shell 中,*
and?
仅在列表上下文中特殊,在 POSIX 或类似 csh 的 shell 中,~
仅在单词开头或后面的某些字符(如 )特殊:
。同样适用=
于zsh
.在某些 shell 中,[
仅当与 . 匹配(有一些限制)时才特殊]
。
在某些 shell(如bash
或 )中yash
,特殊字符(如空白标记分隔符)也会随区域设置而变化。
不同 shell 之间的引用运算符(以删除这些字符的特殊含义)也有很大差异。
类似伯恩的贝壳
sh
类似 Bourne 的 shell(即自 80 年代以来已知在某些系统或其他系统上调用的 shell)的摘要:
伯恩外壳
特殊字符:
"'&|;()^`<>$
、空格、换行符和制表符在不加引号时在简单命令行中是特殊的。#
(早期版本除外)在行首或未加引号的空格、制表符或&|()^<>;`
.{
和}
的特殊之处在于它们是 shell 关键字(因此只有命令位置的单词)。*?[
作为通配符是特殊的,因此仅在列表上下文中。在 的情况下[
,它[...]
是通配符,只需引用[
或]
即可删除特殊含义。=
当它被视为赋值运算符的上下文中时,它是特殊的。也就是说,在一个简单的命令中,对于不跟随参数的所有单词(after 除外set -k
)。
引用运算符
\
引用除换行符之外的所有特殊字符(\<newline>
是一种继续很长的字符的方法逻辑的行到下一个身体的行,以便删除该序列)。请注意,反引号会增加额外的复杂性,因为它们\
首先用于转义结束反引号并帮助解析器。在双引号内,\
只能用于转义自身,"
,$
和`
(\<newline>
仍然是续行符)。在此处文档内,除了"
.\
是在此处文档中转义字符的唯一方法。"..."
双引号转义除自身之外的所有字符,\
,$
和`
。'...'
单引号转义除自身之外的所有字符。
POSIX shell
POSIX shell 的行为与 Bourne shell 基本相似,不同之处在于:
^
不再是特殊字符~
是在某些情况下特别{
允许特殊,因此应加引号。
ksh
与 POSIX 类似,除了:
{string}
,
如果字符串包含不带引号的(或..
在某些情况下和某些版本),则为特殊。- ksh93 有一个额外的特殊引用运算符:
$'...'
具有复杂的规则。该运算符也可以在bash
、zsh
、mksh
FreeBSD 和 busybox中找到(有一些变化)sh
。 ksh93
还有一个$"..."
引用运算符,其工作原理与此类似"..."
,只是字符串需要本地化(可以配置为将其转换为用户的语言)。mksh
忽略$
in$"..."
.- 自以来
ksh93r
,在交互式 shell 中ksh93
支持 csh 风格的历史扩展(默认情况下不启用),这使得命令开头变得特殊。那么在某些上下文中是特殊的(不是在后跟空格或 TAB 时,也不是在此处文档中),并且不会用双引号转义。只有反斜杠(不在双引号内,会删除其特殊含义,但不会以其他方式删除)和单引号会转义它。-H
-o histexpand
^
!
!
\
!
bash
喜欢ksh93
但是:
- 在单字节字符语言环境中,所有空白的(根据区域设置)字符被视为分隔符(如空格或制表符)。实际上,这意味着您应该引用设置了第 8 位的所有字节,以防它们在某些语言环境中可能是空白字符。
- 默认情况下,在交互式实例中启用 csh 历史记录扩展,其注释与上面的 ksh93 相同,只是在较新版本的
bash
,!
有时也并不特殊,当后跟"
. - 与 csh 一样,
%
在命令的开头用于操作作业。%1
将第一个作业置于前台而不是运行%1
命令。与%1 &
将其放在背景中相同...
zsh
喜欢ksh93
但是:
- 与 csh 历史扩展相同的注释
bash
,除了反斜杠可用于!
在双引号内转义,就像 csh 中一样。 =
是特殊的,因为单词的第一个字符(=ls
扩展为/bin/ls
)。%
与命令位置中的bash 的注释相同。{
并且}
还可以在未分隔时打开和关闭命令组({echo text}
如 Bourne 的作品中{ echo text;}
)。- 除了
[
单独的情况外,[
即使不以 . 结束,也需要引用]
。 - 启用该
extendedglob
选项后,#
、^
和~
是通配运算符。 - 有了这个
braceccl
选项,{non-empty-string}
就特别了。 $"..."
不支持。- 作为一个特殊的怪癖,当在单词开头
?
跟随 a (甚至引用或扩展)时并不特殊(以允许工作规范)%
%?name
- 选项
rcquotes
(默认情况下未启用)允许''
在单引号内输入单引号rc
(见下文)。
yash
除了POSIX
那个之外。
- 所有空白字符都被视为分隔符。
- 使用该
brace-expand
选项,实现 zsh 风格的大括号扩展。 - 与命令位置中的 bash 和 zsh 的注释相同
%
(POSIX 模式下除外)。
对于所有 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`'
\
仅删除一个字符的特殊含义:printf '<%s>\n' foo bar\ baz #comment
上面,只有 a 前面的空格字符
\
按字面意思传递给printf
。其他的被 shell 视为标记分隔符。用于
"..."
引用字符,同时仍然允许参数扩展($var
,$#
,${foo#bar}
...)、算术扩展($((1+1))
,也在$[1+1]
某些 shell 中)和命令替换($(...)
或者旧的形式`...`
。实际上,大多数时候,你这样做无论如何都想将这些扩展放在双引号内。您可以使用\
inside"..."
删除仍然特殊的字符(但仅限于它们)的特殊含义。如果字符串包含
'
字符,您仍然可以使用'...'
其余的字符,并使用其他引用机制,可以引用'
像"'"
or\'
or (如果可用)$'\''
:echo 'This is "tricky", isn'\''t it?'
使用现代
$(...)
形式的命令替换。仅使用旧版本`...`
是为了与 Bourne shell 兼容,即对于非常旧的系统,并且仅在变量赋值中使用,如不使用:echo "`echo "foo bar"`"
它不适用于 Bourne shell 或 AT&T 版本的 ksh。或者:
echo "`echo \"foo bar\"`"
这适用于 Bourne 和 AT&T ksh,但不适用于
yash
(2020年编辑:仅在 2.41 及更早版本中,它已在 2.42 中更改/错误报告/犯罪),但使用:var=`echo "foo bar"`; echo "$var"
这将适用于所有人。
用双引号可移植地嵌套它们也是不可能的,所以再次使用变量。还要注意特殊的反斜杠处理:
var=`printf '%s\n' '\\'`
将仅在内部存储一个反斜杠
$var
,因为反斜杠内有一层额外的反斜杠处理(用于\
、 ` 和$
(以及"
除 之外的引用时yash
)),因此您需要var=`printf '%s\n' '\\\\'`
或者
var=`printf '%s\n' '\\\'
反而。
切什家族
csh 和 tcsh 具有显着不同的语法,但与 Bourne shell 仍然有很多共同点,因为它们具有共同的传统。
特殊字符:
"'&|;()^`<>$
、空格、换行符和制表符在不加引号时在任何地方都是特殊的。#
(csh 是作为注释引导符引入的 shell#
)在脚本的开头或在未加引号的空格、制表符或换行符之后是特殊的。*?[
作为通配符是特殊的,所以在列表上下文中{anything}
是特殊的,除了独立的特殊情况{}
(csh 是引入大括号扩展的 shell)。!
和^
作为历史扩展的一部分是特殊的(同样是 csh 的发明),并且引用规则是特殊的。~
(波形符扩展也是 csh 的发明)在某些情况下是特殊的。- 与 bash、zsh、yash 一样,
%
命令位置用于操作作业(又是 csh 的发明)。
引用运算符
它们与 Bourne shell 相同,但行为不同。从语法的角度来看,tcsh 的行为类似于 csh,您会发现许多版本的 csh 都有严重的错误。获取最新版本的 tcsh 以获取大致可以工作的 csh 版本。
\
转义除换行符之外的单个字符(与 Bourne shell 相同)。它是唯一可以转义的引用运算符!
。\<newline>
不会转义它,而是将其从命令分隔符转换为标记分隔符(如空格)"..."
转义除自身之外的所有字符、$
、`
、 换行符和!
。与 Bourne shell 相反,您不能使用\
escape$
和`
inside"..."
,但可以使用\
escape!
或换行符(但不能使用其本身,除非在 a!
或换行符之前)。文字!
是"\!"
,文字\!
是"\\!"
。'...'
转义除自身!
和换行符之外的所有字符。与双引号一样,!
换行符可以用反斜杠转义。- 命令替换只能通过语法进行
`...`
,很难可靠地使用。 - 变量替换的设计也相当糟糕并且容易出错。运算符
$var:q
有助于编写涉及变量的更可靠的代码。
概括
如果可以的话,远离 csh。如果您不能使用:
- 单引号引用大多数字符。
!
和换行符仍然需要一个\
. \
可以转义大多数字符"..."
可以允许在其中进行一些扩展,但是如果它们嵌入换行符和/或反斜杠字符,那就很麻烦了,最好只使用单引号并$var:q
进行变量扩展。如果您想可靠地连接数组的元素,则需要使用循环。
rc
家庭
rc
是plan9
外壳。 plan9 代码现已作为 FLOSS 发布,其用户空间软件包括rc
已移植到 Linux。 Byron Rakitzis 也在 90 年代初编写了 for Unix的克隆版本rc
,并从中派生出es
和akanga
。
这是一种具有更清晰、更好语法的 shell,如果我们不为了向后兼容而使用类似 Bourne 的 shell,那么每个人都会使用它。
rc
/akanga
特殊字符
#;&|^$=`'{}()<>
、SPC、TAB 和 NEWLINE 在不加引号时始终是特殊的。*?[
是通配符运算符。
引用运算符
'...'
是唯一的引用运算符。文字'
用单引号括起来,''
如下所示:
echo 'it''s so simple isn''t it?'
es
es
可以看作是实验性的外壳基于rc
.
但它有一些差异。本问答的有趣之处在于它\
也是一个引用运算符(引用除换行符之外的所有特殊字符),并且还可以用于引入转义序列,例如\n
换行符、\b
反斜杠......
鱼
Fish 是一个相对较新的产品(大约 2005 年),主要用于交互式使用,并且与其他 shell 具有显着不同的语法。
特殊字符
"'\()$%{}^<>;&|
不加引号时总是特殊的(请注意%
(对于 pid 扩展)与其他 shell 有显着差异,并且`
并不特殊)#
(注释)在未加引号的空格、制表符、换行符或;&|^<>
*?
(但不是[...]
)通配运算符
引用运算符
\
引用除换行符之外的单个特殊字符,但要注意它还兼作 C 转义序列 (\n
,\b
...) 引导符。 IOW,\n
不是引用n
而是换行符。"..."
引用除自身以外的所有内容,$
并且可以使用反斜杠和反斜杠来转义它们。\<newline>
是 内部的续行(已删除)"..."
。'...'
引用除自身和之外的所有内容\
,并且您可以使用反斜杠来转义它们。
答案2
1. 逃亡
使用 a 转义所有这些字符\
,如下所示(不适用于换行符/回车符):
$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.
2.双引号
将整个文本括在"
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!!!
3. 单引号
与双引号相同,但没有特殊标记。
$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof