sed - 在模式之间应用替换

问题描述 投票:1回答:3

我有两个模式STARTEND,并希望用这些模式之间的下划线替换每个空间。

Lorem ipsum dolor START sit amet, consectetur END adipiscing elit.

应该转变为

Lorem ipsum dolor START_sit_amet,_consectetur_END adipiscing elit.

我知道正则表达式用下划线替换每个空格

sed 's/ /_/g'

我也知道如何匹配两种模式之间的部分

sed 's/.*START\(.*\)END.*/\1/g'

但我不知道如何将这两件事结合起来。

regex sed substitution
3个回答
2
投票

作为替代方案,您可以使用Perl:

perl -pe 's/(START.*?END)/$1=~s#\s#_#gr/ge'

(START.*?END)模式匹配STARTEND之间的子串,同时将其捕获到组1中,然后s#\s#_#gr用组中的\s替换每个单个空格(_)。

或者,如果您使用不支持r选项的Perl:

perl -pe 's/(?:START|\G(?!^))(?:(?!END).)*?\K\s/_/g'

参见online demosecond regex demo online

(?:START|\G(?!^))(?:(?!END).)*?\K\s比赛

  • (?:START|\G(?!^)) - START子串或上一次成功比赛结束(与\G(?!^)
  • (?:(?!END).)*? - 任何字符,但换行符,而不是启动END子字符串,尽可能少
  • \K - 匹配重置运算符,丢弃先前匹配的文本
  • \s - 一个空白字符。

1
投票

你可以使用这个awk来完成你的工作:

awk -v ts='START ' -v te='END ' '{
   while (n = index($0, ts)) {
      m = index($0, te)
      if (m > n) {
         s = substr($0, n, m-n)
         gsub(/[[:blank:]]+/, "_", s)
         $0 = substr($0, 1, n-1) s substr($0, m)
      }
   }
} 1' file

Lorem ipsum dolor START_sit_amet,_consectetur_END adipiscing elit.

1
投票

使用GNU awk:

awk -v RS='(START|END)' 'RT=="END"{gsub(" ","_")}{printf "%s%s",$0,RT}' file

这依赖于记录分隔符RS设置为STARTEND

如果到达END标记,则更新记录以使用函数gsub()替换带下划线的空格。

最后一个语句打印整个记录,包括记录终止符RT(与RS匹配)。

请注意,此解决方案允许STARTEND跨越不同的行(并且必须在同一行上)。

© www.soinside.com 2019 - 2024. All rights reserved.