我一直在尝试更好地理解某些命令中如何使用反斜杠。我理解它用于转义特殊字符(例如echo 'that'\''s no moon'
)的用法,但其他命令的输出有点令人困惑。例如:
rpm-qa rpmname\*
grep '\s/tmp' /etc/fstab
有人可以帮我分解这些吗?也对您可能知道的任何其他用法感到好奇。谢谢你!
答案1
反斜杠通常用来表示“让下一个字符代表自己,而不是赋予它特殊的含义”。我们说反斜杠引号下一个字符。这种含义存在于许多编程语言中,包括 shell 语法。例如,在 中rpm-qa rpmname\*
,反斜杠导致*
字符在参数中传递给rpm-qa
命令。相反,rpm-qa rpmname*
将替换rpmname*
为当前目录中以rpmname
. (如果没有匹配的文件,则 bash 不会出现rpmname*
;默认情况下,zsh 会抱怨没有匹配项。)
shell 提供了另一种按字面解释字符的方式,即使其代表自身而不是以某种特殊方式解释。这就是引用,它取消了整个字符序列的特殊含义。有两种引号:单引号'
使每个字符代表自己,直到下一个单引号,而双引号则为"
少数字符( 、 和 )保留"
特殊$
含义。在 中,该命令接收一个参数,该参数是(用文字字符串编写的,而不是在该特定情况下有任何具有特殊含义的字符)的串联,(反斜杠单引号取消了该单引号的特殊含义,因此这会扩展为一个单引号字符),并且(空格失去了其特殊含义,因为它们位于引号内:它们不是分隔参数,而是参数的一部分)。\
`
echo 'that'\''s no moon'
echo
that
'
s no moon
在 shell 中,当反斜杠具有特殊含义时,通常是引用下一个字符。但:
- 在单引号内,反斜杠没有特殊含义。
- 在双引号内,反斜杠仅引用下一个字符(如果它是 之一)
"$\`
。否则,反斜杠和后面的字符都按字面解释,例如"\a"
是两个字符的字符串\a
。 - 在美元单引号文字中,反斜杠具有不同的含义,类似于C。反斜杠后跟八进制数字或某些字母提供了输入字符的替代方法,这对于不可打印的字符很有用。例如,
\n
是小写的N,"\n"
是反斜杠+n,但是$'\n'
是换行符。
在 中grep '\s/tmp' /etc/fstab
,单引号导致grep
接收参数\s/tmp
。这个论点是一个正则表达式。正则表达式有许多语法变体,但大多数基于以下两个标准之一:POSIX 基本正则表达式 (BRE) 和扩展正则表达式 (ERE)。 ERE 遵循广泛的惯例,即反斜杠后跟除字母或数字之外的任何内容来引用以下字符。但由于历史原因,在 BRE 中,反斜杠有时会使下一个字符变得特殊,否则它不会如此。在本例中,\s
是基本正则表达式语法的 GNU grep 扩展,可用于 BRE 和 ERE,表示一个空白字符。因此列出了前面包含空格或制表符的grep '\s/tmp' /etc/fstab
行。/etc/fstab
/tmp
答案2
我假设您正在使用 bash 或类似的东西。
首先,您必须了解 bash 如何评估您的输入。您可以在 bash 中使用许多特殊字符。例如,其中一些是* ; ~ $
当您输入内容时,bash 将尝试替换所有应该替换的字符。例如以$
符号开头的变量。将*
替换为您当前所在目录中存在的每个文件/目录(用 确定pwd
)。
如果替换步骤完成,bash 将最终执行(带有fork()
)您指定的程序。
告诉\
bash 忽略给定的特殊字符:\*
答案3
你是对的,有一个常见的约定,即反斜杠用于转义字符,或者所述字符具有特殊含义并且您希望它是字面意思:
# echo 'It\'s a string!'
在上面的示例中,撇号用于分隔文字字符串,但由于字符串中需要撇号,因此必须对其进行转义。
另一种情况则相反,当您需要一个“正常”字符具有某种特殊含义时:
# grep '\s/tmp' /etc/fstab
在上面的例子中,反斜杠是告诉 grep 具有s
特殊含义并且不是文字s
(是正则表达式空格:空格、制表符、换行符、回车符、垂直制表符)
换句话说,当一个字符有两种可能的含义时,您将其转义,使其成为次要含义。
编辑:
对于你的第一个例子:
rpm-qa rpmname\*
这里*
有一个特殊的含义(以“rpmname”开头的任何内容),但为了避免 shell 尝试扩展它,您需要转义它,以便命令rpm
获取文字*
并可以相应地处理它。
这会导致字符串被解释多次,并且当字符串由多个命令传递时,这可能是一场真正的斗争。
答案4
用于\
转义特殊字符和触发正则表达式。
您的rpm
命令是 escaping *
,在这种情况下,其功能与不转义它相同。 RPM 知道这*
是一个无效的包字符,因此即使您转义它它也会解释它。转义特殊字符更常用于处理非字母数字文件名等情况。
假设有两个文件,一个名为“foo-biz-bar”,另一个名为“foo*bar”,我们只想看到“foo*bar”。出现下面的第一个结果是因为未转义的*
是 blob 通配符。
$ ls foo*bar
foo*bar foo-biz-bar
$ ls foo\*bar
foo*baz
\s
示例中的是grep
一个正则表达式,表示“任何空白”,即制表符和空格。
进一步阅读
很难在线获得详尽的正则表达式列表,但您可以开始这里。
对我帮助很大的一本书是《Unix Shells by Examples》。广泛的sed
、grep
、 和awk
用法也都涵盖了。