【问题标题】:Grep with a regex character range that includes the NULL character使用包含 NULL 字符的正则表达式字符范围的 Grep
【发布时间】:2021-05-31 08:11:47
【问题描述】:

当我在 BSD grep 的正则表达式字符范围中包含 NULL 字符 (\x00) 时,结果出乎意料:没有字符匹配。为什么会这样?

这是一个例子:

$ echo 'ABCabc<>/ă' | grep -o [$'\x00'-$'\x7f']

这里我希望直到最后一个字符之前的所有字符都匹配,但是结果是没有输出(没有匹配)。

或者,当我从 \x01 开始字符范围时,它按预期工作:

$ echo 'ABCabc<>/ă' | grep -o [$'\x01'-$'\x7f']
A
B
C
a
b
c
<
>
/

另外,这是我的 grep 和 BASH 版本:

$ grep --version
grep (BSD grep) 2.5.1-FreeBSD

$ echo $BASH_VERSION
3.2.57(1)-release

【问题讨论】:

    标签: bash grep hex bsd null-character


    【解决方案1】:

    在 BSD grep 上,你也许可以使用这个:

    LC_ALL=C grep -o '[[:print:][:cntrl:]]' <<< 'ABCabc<>/ă'
    
    A
    B
    C
    a
    b
    c
    <
    >
    /
    

    或者您可以使用home brew 包安装gnu grep 并运行:

    grep -oP '[[:ascii:]]' <<< 'ABCabc<>/ă'
    

    【讨论】:

      【解决方案2】:

      注意到$'...' is a shell quoting construct,这个,

      $ echo 'ABCabc<>/ă' | grep -o [$'\x00'-$'\x7f']
      

      将尝试将文字 NUL 字符作为命令行参数的一部分传递给grep。这在任何类 Unix 系统中都是不可能的,因为命令行参数作为以 NUL 结尾的字符串传递给进程。所以实际上,grep 只看到参数-o[

      您需要创建一些与 NUL 字节匹配的模式,而不是从字面上包含它。但我不认为grep 支持\000\x00 自行转义。不过 Perl 确实如此,所以这会打印带有 NUL 的输入行:

      $ printf 'foo\nbar\0\n' |perl -ne 'print if /\000/'
      bar
      

      顺便说一句,至少 GNU grep 似乎不喜欢那种范围表达式,所以如果你要使用它,你会做一些不同的事情。在C 语言环境中,[[:cntrl:][:print:]]' 可能可以匹配从\x01\x7f 的字符,但我没有全面检查。 manual for grep has some descriptions of the classes


      还要注意[$'\x00'-$'\x7f'] 有一对不带引号的[],shell glob 也是如此。这与 NUL 字节无关,但如果您有与 glob 匹配的文件(任何单字母名称,如果 glob 在您的系统上工作 - 它不适用于我的 Linux),或者有 failglobnullglob 设置,它可能会给出你不想要的结果。相反,也要引用方括号:$'[\x00-\x7f]'

      【讨论】:

      • grep ['a'-'b']grep '[a-b]' 也一样吗?
      • @oguzismail,除了第一个是 glob,不是吗?
      • 第一个是一个 glob 并不是一个可以忽略的差异。它们不一样。
      • 无论如何都会误导。 ['a'-'b'] 可能会扩展为空字符串 (nullglob)、abab[a-b],或者可能会导致命令失败 (failglob),而 @987654353 @ 将永远是 [a-b]
      • @oguzismail,是的,实际上你是对的,假设它完全有效,那么问题中的 glob 将匹配任何一个字母的名称。我倾向于故意忽略failglobnullglob 以及匹配奇怪文件名的机会,以便保持重点,但一个字母的文件名更可能是一个问题。如果你愿意,可以称之为懒惰,但遗憾的是,关于 shell 语言所有怪癖的免责声明相当长,无法包含在每篇文章中......
      猜你喜欢
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      • 1970-01-01
      • 1970-01-01
      • 2019-06-22
      • 2015-08-28
      相关资源
      最近更新 更多