sed表达式,char xx:由连字符引起的无效范围结束错误

时间:2014-08-06 21:48:23

标签: regex bash unix sed

给定一个文件:

2014-08-01 20:13:17.666 xxxxxxxxxx
2014-08-01 20:13:17.666 xxxxxxxxxx
2014-08-01 20:13:17.666 xxxxxxxxxx
......

我试图使用sed删除微秒:

GNU sed version 4.2.1
Copyright (C) 2009 Free Software Foundation, Inc.

以下内容失败,错误消息“sed:-e expression#1,char 38:无效范围结束”

sed 's/\([0-9][0-9\- :]*\)\.[0-9]\{3\}/\1/g' < a.csv

然而,vi a.csv并搜索

\([0-9][0-9\- :]*\)\.[0-9]\{3\}

工作正常。

rootcause是转义的连字符。如果我删除了转义的连字符,sed将不会抱怨但它与预期的模式不匹配。我已经尝试了不同的方法来逃避连字符无济于事。

解决方法是明确写出整个日期时间格式,如下所示:

sed 's/\([0-9][0-9]*-[0-9][0-9]-[0-9][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]\)\.[0-9]\{3\}/\1/g'

这种解决方法看起来很丑陋而且很麻烦。我确实认识到sed和vi之间的底层RE引擎是不同的。但是,我喜欢

  1. 明白为什么甚至在sed中逃避连字符失败
  2. 如何修改sed的RE以使其更优雅。
  3. sed error "Invalid range end"

    相关但未解决

1 个答案:

答案 0 :(得分:5)

在字符类中,连字符必须是第一个或最后一个。试图用反斜杠转义它是行不通的(而是在类中添加反斜杠)。

有多个sed方言和多个其他正则表达式实现的工作方式不同,但在这种情况下,诊断相当简单。修复:

sed 's/\([0-9][-0-9 :]*\)\.[0-9]\{3\}/\1/' < a.csv

(我也删除了/g标志,因为它在这里似乎是多余的。当然,这种模式的每一行不超过一次?)