【问题标题】:using extended regular expressions in sed在 sed 中使用扩展正则表达式
【发布时间】:2016-11-11 15:31:51
【问题描述】:

我正在尝试在 sed 中做一些疯狂的正则表达式,但不允许这样做

我只是没有得到正则表达式还是 sed 中的正则表达式不同

我正在使用的文件是这样的

46,uie,ieo
39,ieu,tii
44-46,yut,til
45,dkd,ytu
65,dkd,ytu
40-45,dkd,ytu

当我这样做时

cat text.txt | sed s/^4[0-9],//g

我几乎得到了我想要的,我得到了

uie,ieo
39,ieu,tii
44-46,yut,til
dkd,ytu
65,dkd,ytu
40-45,dkd,ytu

但我想摆脱像 40-45 和 44-46 这样的人 所以我试过了

cat text.txt | sed s/^4[0-9](-4[0-9])?,//g 
-bash: syntax error near unexpected token `('

当我尝试时

cat text.txt | sed s/^4[0-9]-?4?[0-9]?,//g

我刚刚得到

46,uie,ieo
39,ieu,tii
44-46,yut,til
45,dkd,ytu
65,dkd,ytu
40-45,dkd,ytu

所以没有过滤任何东西

谢谢!

【问题讨论】:

  • 用反斜杠转义括号,如下所示:cat test | sed -r s/^4[0-9]\(-4[0-9]\)?,//g
  • 它是一个 3 列的 csv 文件,要删除第一列,请使用 cut
  • @CasimiretHippolyte:他显然不想删除第一列,除非它在 ​​40 到 49 的范围内。
  • @KeithThompson:你说得对,我没看到。

标签: bash unix sed


【解决方案1】:
cat text.txt | sed s/^4[0-9](-4[0-9])?,//g

两个问题。

首先,您需要将参数引用到sed。它包含了shell可以识别的元字符,例如(?;您需要引用参数,以便 shell 将其视为一个字符串并且不会尝试解释它。

cat text.txt | sed 's/^4[0-9](-4[0-9])?,//g' # this still doesn't work

其次,sed 默认不使用扩展正则表达式。如果您使用的是 GNU sed(输入 sed --version 确认这一点),您可以使用 -E 选项来启用扩展正则表达式:

cat text.txt | sed -E 's/^4[0-9](-4[0-9])?,//g'

或者您可以使用反斜杠让sed 识别()? 字符:

cat text.txt | sed 's/^4[0-9]\(-4[0-9]\)\?,//g'

最后,这是Useless Use of catsed 完全能够从标准输入或指定文件读取输入;您无需通过来自cat 的管道将其输入:

sed 's/^4[0-9]\(-4[0-9]\)\?,//g' text.txt

-E 选项由 POSIX 指定;我认为这是一个相对较新的添加。 GNU sed 自 2006 年以来一直支持 -E(最初是为了与 BSD sed 兼容),但目前在任何发布的版本中都没有记录。 2013 年添加了文档,但 GNU sed 的最新官方版本是 2012 年的 4.2.2。

2021 年 11 月 8 日更新没有似乎 POSIX 指定了 -E 选项(请参阅 https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html),尽管它已被提议。

GNU sed 4.7 版的手册说:

'-E'
'-r'
'--regexp-extended'
     Use extended regular expressions rather than basic regular
     expressions.  Extended regexps are those that 'egrep' accepts; they
     can be clearer because they usually have fewer backslashes.
     Historically this was a GNU extension, but the '-E' extension has
     since been added to the POSIX standard
     (http://austingroupbugs.net/view.php?id=528), so use '-E' for
     portability.  GNU sed has accepted '-E' as an undocumented option
     for years, and *BSD seds have accepted '-E' for years as well, but
     scripts that use '-E' might not port to other older systems.  *Note
     Extended regular expressions: ERE syntax.

手册链接到 Austin Group Defect Tracker 中的 this entry,该链接将截至 2020 年 3 月 18 日的问题列为“已解决 => 已应用”。也许它还没有应用于 opengroup.org 网站。

【讨论】:

  • -E 而不是 -r 更便携。
  • "-E 选项由 POSIX 指定;我认为这是一个相对较新的添加。"你确定吗? man 1p sed 中没有。
  • @ban_javascript 不,我不完全确定。请参阅上面的更新。
【解决方案2】:

你可以使用awk:

awk -F, '!/^4[0-9]\>/;{print $2,$3}' text.txt

详情:

!/^4[0-9]\>/ # returns 1 (true) when the line doesn't start with a number between
             # 40 and 49 ( `\>` figures a boundary )
             # (when the expression returns true, the whole line is printed and 
             # awk jumps to the next line)

{print $2,$3} # otherwise fields 2 and 3 are printed

-F, 定义字段分隔符。

【讨论】:

    【解决方案3】:

    您似乎弄错了一些基本的 UNIX 内容。需要引用sed 的那些参数。它们被 shell 解释为文件名 glob。此外,这是对 cat 的一种额外使用,您可以通过使用 shell 重定向 < 获得相同的效果(并且更有效)。此外,在sed 正则表达式中,()? 是普通字符,除非使用\ 进行转义。所以结果就是这对我有用:

    sed 's/^4[0-9]\(-4[0-9]\)\?,//g' < text.txt
    

    【讨论】:

      猜你喜欢
      • 2012-03-06
      • 2017-10-17
      • 2012-10-19
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 2016-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多