Using sed to replace the last occurrence of character

6,645

Solution 1

You could pipe through rev, replace the first occurrence, and then through rev again:

rev | sed -e 's/|/`/' | rev

Alternatively, in pure sed, you want to replace | followed by anything not including | with ` followed by the same sequence:

sed -e 's/|\([^|]*\)$/`\1/'

I'd argue that the first of those is easier to read and understand.

Solution 2

You can use the fact that .* is greedy:

sed 's/\(.*\)|/\1`/'

Or use:

sed 's/|\([^|]*\)$/`\1/'

To match on | followed by something that doesn't contain | til the end of line as already shown by Toby, but that approach only works for single character replacements.

To replace it in a multiline string shell variable, with GNU sed, you can use the -z option which treats the input as NUL delimited instead of newline delimited:

var=$(printf %s "$var" | sed -z '...')

Another approach would be to do the substitution using standard parameter expansion operators:

case $var in
  (*'|'*) var=${var%'|'*}'`'${var##*'|'}
esac

Or with those sed commands translated to their shell equivalent:

In ksh93:

var=${var/@(*)'|'/\1'`'}
var=${var/%'|'*([^'|'])/'`'\1}

In bash (assuming the string doesn't contain byte sequences not forming valid characters in the current locale):

re='(.*)\|(.*)'
[[ $var =~ $re ]] && var=${BASH_REMATCH[1]}'`'${BASH_REMATCH[2]}

In zsh:

set -o extendedglob
var=${var/(#b)(*)'|'/$match[1]'`'}

var=${var/%(#b)'|'([^'|']#)/'`'$match[1]}
Share:
6,645

Related videos on Youtube

Chris Pavey
Author by

Chris Pavey

Updated on September 18, 2022

Comments

  • Chris Pavey
    Chris Pavey over 1 year

    I'm trying to replace the last occurrence of a character within a multi line string variable.

    I need to replace the last | with a `.

  • Chris Pavey
    Chris Pavey over 5 years
    Thank you. But these expressions replace the last instance on each line. I'd like to replace the very last occurrence within the variable.
  • Chris Pavey
    Chris Pavey over 5 years
    Thank you. But these expressions replace the last instance on each line. I'd like to replace the very last occurrence within the variable.
  • Toby Speight
    Toby Speight over 5 years
    If you have GNU sed (likely, as you're on Linux), you can set the line separator to be the NUL character, using -z or --null-data, so your entire input will be considered as a single line.
  • Stéphane Chazelas
    Stéphane Chazelas over 5 years
    @Chris, I had missed that part of your requirement. See edit.