在 CentOS 8 上,此
grep
表达式不返回匹配的字符串:
% dmidecode -t memory | grep -E '^[ \t]+Size: [0-9]+'
然而,这个确实正确返回匹配的行(在同一发行版上):
% dmidecode -t memory | grep -E '^[[:space:]]+Size: [0-9]+'
这种行为的原因是什么?正如您所看到的,两次
grep
都是在扩展正则表达式模式下调用的。
这里的问题是
\t
字符序列。这not匹配grep
正则表达式中的制表符,它匹配字符t
(不管它是基本方言还是扩展方言RE)。它不像其他一些工具(包括使用 PCRE 方言的 GNU grep
)那样被视为特殊的转义序列。
证人:
# printf /does/ treat \t and \n special in a format
$ printf "a\tb\n" | grep "a[ \t]b" # No match
$ printf "atb\n" | grep "a[ \t]b" # Match
atb
$ printf "a\tb\n" | grep "a[[:space:]]b" # Match
a b
$ printf "a\tb\n" | grep "a[[:blank:]]b" # Match
a b
$ printf "a\tb\n" | grep "a\sb" # Match, \s is a GNU grep extension
a b
$ printf "a\tb\n" | grep -P "a\sb" # Match, GNU grep using PCRE
a b
$ printf "a\tb\n" | grep -P "a[ \t]b" # Match, GNU grep using PCRE.
a b
我一直使用ERE(
egrep
,grep -E
),所以切换到另一种“语言”对我来说不是一个选择。
切入正题:
% dmidecode -t memory | grep -E '^[ '$'\t'']+Size: [0-9]+'
这可能会有点令人困惑。也许这会让事情变得更清楚一些:
% dmidecode -t memory | grep -E "^[ "$'\t'"]+Size: [0-9]+"
也就是说,停止“字符串引用”并发出一个
$'\t'
,这将是输出实际制表符的“简写”。这在 bash 中对我有用。广泛搜索,没有找到很多(任何?)答案表明这一点,所以希望这是最好的!可惜egrep
(grep -E
)不喜欢制表符,对吧?
使用
[[:blank:]]
匹配空格字符和制表符。您也可以省略-E
:
grep '^[[:blank:]]+ Size: [0-9]+'