如果你使用这段代码:
echo -e '\t\t\tString' | grep '^[\t]*String'
结果是空白的,因为它不匹配,但是:
echo -e '\t\t\tString' | grep $'^[\t]*String'
作品。我发誓我一定在我的脚本和终端中使用了第一行代码一百次,而从未使用过这样的“$”字符,而且它似乎总是有效。最近有什么变化吗?为什么需要“$”字符?或者我做错了什么?
答案1
ANSI-C 引用
根据 Bash 手册,这称为ANSI-C 引用。手册说:
形式的词$'字符串'受到特殊对待。该单词扩展为字符串,并按照 ANSI C 标准指定的方式替换反斜杠转义字符。
实际上,这意味着'\t'
不会扩展为制表符,但$'\t'
会扩展。输出应该等同于 using echo -e
,但可以在任何使用字符串的地方使用,而不需要命令替换。
像 GNU sed 这样的实用程序会执行自己的转义字符扩展,但 GNU grep 不会。 Bash shell(而不是 grep)会扩展 ANSI-C 带引号的字符串中的转义字符。如果没有 ANSI-C 引用,您发布的正则表达式将不包含与输入匹配的制表符。
答案2
您可能应该意识到不存在单一类型的正则表达式。至少有basic regular expressions
或BRE
(有时只有RE
)、extended regular expressions
或ERE
和perl compatible regular expressions
或PCRE
。所有这些语言使用的语法都略有不同。当前版本GNU grep
支持所有三个并且BRE
是默认的。因为ERE
您需要使用-E
option 和 for PCRE
-P
option。您的示例仅适用-P
于基本和扩展 RE,反斜杠失去其含义并[\t]
匹配反斜杠或字符 t。您可能在PCRE
默认支持的其他语言中使用该模式,这是有道理的,因为它们是最强大的版本。或者也许你在alias grep='grep -P'
某个地方。
答案3
如果省略 . 则第一行有效^
。也许它有效,但没有按照您想象的方式工作?我怀疑grep
其行为在如此重要的一点上发生了变化。
echo
默认情况下不翻译转义序列。你需要-e
为此。与外壳类似。您需要$'...'
使 shell 使用转义序列。