我有以下字符串:
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\}
是如何解决它的。还有其他解决方案吗?
答案 0 :(得分:1)
\{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
答案 1 :(得分:0)
因为sed
使用default的basic regular expression
。有关basic regular expression
和extended 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
答案 2 :(得分:0)
如果月份和数据遵循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
注意:带有-E
的{{1}}选项启用扩展的正则表达式,如果不支持,则使用sed
选项。