【问题标题】:Including optional character in regex with sed使用 sed 在正则表达式中包含可选字符
【发布时间】:2019-04-18 13:36:58
【问题描述】:

我有以下字符串:

setenv run_area1 root/test1/Apr14_2019_10_32_39/dummy
setenv area2 root/test2/Aug23_2017_14_25_56/dummy
setenv run_area3 testRun/test1/blue_Apr14_2019_08_56_48/dummy/
setenv area4 testRun/test2/Aug23_2017_14_26_03/thing2

我想用[DATE] 替换日期如下:

setenv run_area1 root/test1/[DATE]/dummy
setenv area2 root/test2/[DATE]/dummy
setenv run_area3 testRun/test1/blue[DATE]/dummy/
setenv area4 testRun/test2/[DATE]/thing2

我必须使用 sed,所以我编写了以下命令:

sed 's|[A-Z][a-z]*[0-9]*_[0-9]*_[0-9]*_[0-9]*_[0-9]*|[DATE]|g'

它适用于字符串,但适用于以下字符串:

setenv run_area3 testRun/test1/blue_Apr14_2019_08_56_48/dummy/

我明白了:

setenv run_area3 testRun/test1/blue_[DATE]/dummy/

我正在寻找一种在正则表达式中使用_ 的方法。在 perl 中,我知道我可以使用 (_|) 这样的东西,所以 _ 是可选的。我也可以使用?。 对于以前的线程,我看到基本的sed 不包括这些选项,我需要使用\{0,1\}。 (link)。 问题是,我似乎无法理解\{0,1\} 是如何解决它的。还有其他解决方案吗?

【问题讨论】:

  • 没有时间测试,但我希望's|_*[A-Z][a-z]*[0-9]*.......|....| 能够工作。祝你好运。

标签: sed


【解决方案1】:

BRE 中的\{0,1\} 是一个正则表达式区间,表示0 to 1 repetitions of the preceding expression 与ERE 中的? 相同(技术上在ERE 中它被定义为0 _or_ 1,但这是同一组值!)即前面的表达式是可选的。

使用任何 POSIX sed:

$ sed 's/_\{0,1\}[[:upper:]][[:lower:]]*[0-9]*\(_[0-9]*\)\{4\}/[DATE]/' file
setenv run_area1 root/test1/[DATE]/dummy
setenv area2 root/test2/[DATE]/dummy
setenv run_area3 testRun/test1/blue[DATE]/dummy/
setenv area4 testRun/test2/[DATE]/thing2

【讨论】:

    【解决方案2】:

    如果月份和数据遵循MMMDD 格式,您可以认为这样的表达式在记录中是唯一的,并将整个脚本基于该假设。有点像下面:

    sed -E 's/^(.*)([[:alpha:]]{3}[[:digit:]]{2})([^/]+)\/(.*)$/\1[DATE]\/\4/;s/_\[DATE\]/[DATE]/' filename
    

    输出

    setenv run_area1 root/test1/[DATE]/dummy
    setenv area2 root/test2/[DATE]/dummy
    setenv run_area3 testRun/test1/blue[DATE]/dummy/
    setenv area4 testRun/test2/[DATE]/thing2
    

    注意:带有sed-E 选项启用扩展正则表达式,如果不支持,请使用-r 选项。

    【讨论】:

    • 仅供参考 -E 将与 OSX/BSD sed 和更新版本的 GNU sed 一起使用,因此它比 -r 更好的可移植性。 -r 仅适用于 GNU sed,并且仅当您使用不支持 -E 的旧版本时才需要。
    【解决方案3】:

    因为sed 使用basic regular expression by defaultbasic regular expressionextended regular expression的区别可以参考这个link

    如果您想使用extended regular expression 支持的功能。您必须使用 -r 选项明确告诉 sed。

    所以对于 GNU sed,下面的脚本实际上会做同样的事情。

    sed 's|_\?[A-Z][a-z]*[0-9]*_[0-9]*_[0-9]*_[0-9]*_[0-9]*|[DATE]|g' textfile
    
    sed -r 's|_?[A-Z][a-z]*[0-9]*_[0-9]*_[0-9]*_[0-9]*_[0-9]*|[DATE]|g' textfile
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      相关资源
      最近更新 更多