【问题标题】:sed - apply substitution between patternssed - 在模式之间应用替换
【发布时间】:2018-09-12 10:37:05
【问题描述】:

我有两个模式 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


    【解决方案1】:

    你也可以使用 Perl:

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

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

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

    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 - 一个空格字符。

    【讨论】:

      【解决方案2】:

      您可以使用此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.
      

      【讨论】:

        【解决方案3】:

        使用 GNU awk:

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

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

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

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

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

        【讨论】:

        • @DOWNVOTER:请解释为什么?
        猜你喜欢
        • 2016-06-17
        • 1970-01-01
        • 2016-08-21
        • 2023-02-04
        • 2018-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多