Sed substitute recursively

前端 未结 6 842
我在风中等你
我在风中等你 2020-12-28 18:35

echo ddayaynightday | sed \'s/day//g\'

It ends up daynight

Is there anyway to make it substitute until no more match ?

相关标签:
6条回答
  • 2020-12-28 19:15

    The following works:

    $ echo ddayaynightday | sed ':loop;/day/{s///g;b loop}'
    night
    

    Depending on your system, the ; may not work to separate commands, so you can use the following instead:

    echo ddayaynightday | sed -e ':loop' -e '/day/{s///g
                                                   b loop}'
    

    Explanation:

    :loop       # Create the label 'loop'
    /day/{      # if the pattern space matches 'day'
      s///g     # remove all occurrence of 'day' from the pattern space
      b loop    # go back to the label 'loop'
    }
    

    If the b loop portion of the command is not executed, the current contents of the pattern space are printed and the next line is read.

    0 讨论(0)
  • 2020-12-28 19:15

    Ok, here they're: while and strlen in bash. Using them one may implement my idea:

    Repeat until its length will stop changing.

    There's neither way to set flag nor way to write such regex, to "substitute until no more match".

    0 讨论(0)
  • 2020-12-28 19:25

    This might work for you:

    echo ddayaynightday | sed ':a;s/day//g;ta'
    night
    
    0 讨论(0)
  • 2020-12-28 19:30

    My preferred form, for this case:

    echo ddayaynightday | sed -e ':loop' -e 's/day//g' -e 't loop'
    

    This is the same as everyone else's, except that it uses multiple -e commands to make the three lines and uses the t construct—which means "branch if you did a successful substitution"—to iterate.

    0 讨论(0)
  • 2020-12-28 19:34

    with bash:

    str=ddayaynightday
    while true; do tmp=${str//day/}; [[ $tmp = $str ]] && break; str=$tmp; done
    echo $str
    
    0 讨论(0)
  • 2020-12-28 19:36

    The g flag deliberately doesn't re-match against the substituted portion of the string. What you'll need to do is a bit different. Try this:

    echo ddayaynightday | sed $':begin\n/day/{ s///; bbegin\n}'
    

    Due to BSD Sed's quirkiness the embedded newlines are required. If you're using GNU Sed you may be able to get away with

    sed ':begin;/day/{ s///; bbegin }'
    
    0 讨论(0)
提交回复
热议问题