【问题标题】:Grep's "Invalid range end" ­— bug or feature?Grep 的“无效范围结束”——错误还是功能?
【发布时间】:2014-11-05 09:58:53
【问题描述】:

我有这三个文件:

$ cat pattern-ok 
['\-]
$ cat pattern-buggy 
[\-']
$ cat text 
abc'def-ghi

现在,以下是我不知道的错误还是正则表达式功能?

$ cat text | grep -f pattern-ok 
abc'def-ghi
$ cat text | grep -f pattern-buggy
grep: Invalid range end

我正在使用:

$ grep --version | head -n 1
grep (GNU grep) 2.20

【问题讨论】:

  • 通过谷歌找到这个;事实证明,有时这个错误是由于 glibc 错误而意外引起的。 bugzilla.redhat.com/show_bug.cgi?id=583011
  • 我得到这个是因为我写了 [A-z0-9a-z] 并且 grep 是对的(第一个 z 应该是大写的)

标签: regex grep gnu


【解决方案1】:

这是因为您在其他字符中使用了连字符,因此grep 将其理解为一个范围,而这恰好是无效的。

你基本上在做

grep "[\-']" file

这是由grep 解释的,因为您提供了一系列要检查的字符,例如grep "[a-z]" file。但是\'的范围是无效的,所以报错。

为什么另一个在工作?你可能会问自己。因为你正在做的是:

grep "['\-]" file

在这种情况下,您正在文件中查找字符 '\-

查看另一个示例,我想在给定字符串中查找字符 a-3

$ echo "23-2" | grep -o '[a-3]'
grep: Invalid range end
$ echo "23-2" | grep -o '[a3-]'
3
-
$ echo "23-2" | grep -o '[a3\-]'
3
-

所以根本问题是您在 [] 块内使用表达式 some character + - + another character 并试图将其读取为 some characteranother character 之间的字符范围.


你怎么解决的?

如果您想匹配字符 - 等,只需将其添加到表达式的边缘:作为第一项或最后一项。

来自man grep

字符类和括号表达式

括号表达式是由 [ 和 ] 括起来的字符列表。它 匹配该列表中的任何单个字符;如果第一个字符 列表中的插入符号 ^ 然后它匹配任何不在的字符 名单。例如,正则表达式 [0123456789] 匹配 任何一位数。

在括号表达式中,范围表达式由两个 用连字符分隔的字符。它匹配任何单个字符 使用区域设置在两个字符(包括)之间进行排序 整理顺序和字符集。例如,在默认的 C 语言环境,[a-d] 等价于 [abcd]。许多语言环境对字符进行排序 按字典顺序,并且在这些语言环境中 [a-d] 通常是 不等同于 [abcd];它可能等价于 [aBbCcDd],因为 例子。获取括号的传统解释 表达式,您可以通过设置 LC_ALL 来使用 C 语言环境 环境变量为值 C。

最后,某些命名的字符类别在 括号表达式,如下所示。他们的名字不言自明, 它们是 [:alnum:], [:alpha:], [:cntrl:], [:digit:], [:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:], 和 [:xdigit:]。例如,[[:alnum:]] 表示字符类 当前语言环境中的数字和字母。在 C 语言环境和 ASCII 中 字符集编码,这与 [0-9A-Za-z] 相同。 (笔记 这些类名中的括号是符号的一部分 名称,并且必须包含在括号中 括号表达式。)大多数元字符失去了它们的特殊含义 括号内的表达式。要包含文字 ] 放置它 列表中的第一位。同样,要包含文字 ^ 放置它 任何地方,但首先。 最后,要包含一个文字 - 放置它 最后。

【讨论】:

  • 那么如何将- 转义为普通字符?将它放在[] 组的末尾是唯一的方法吗?
  • 是的,这将解决它。您可以在表达式的前面或后面使用-,这样它就不会被视为一个范围。
  • 所以 没有办法 只是逃避它并将其放在[] 组中的任何位置? :O 很奇怪。在我的一生中,我一直像[abc\-def] 一样使用它并且不知道它的真正含义。谢谢。
  • 是的,确实很奇怪。我刚刚在答案中添加了man grep 中的引用,它准确地说明了这一点。
  • 具体来说,从“反斜杠”到“单引号”的范围是无效的,因为“反斜杠”的ASCII码大于比“单引号”的。范围 a-z 没问题,因为 a 小于 z,ASCII 方式。
【解决方案2】:

为了避免范围值你可以使用fgrep

【讨论】:

  • 我使用了这个解决方案,因为我正在解析一个文件路径数组。
猜你喜欢
  • 2013-05-14
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-17
  • 2016-07-17
  • 1970-01-01
  • 2014-09-30
相关资源
最近更新 更多