Using sed to replace the last occurrence of character
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]}
Related videos on Youtube
Chris Pavey
Updated on September 18, 2022Comments
-
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 over 5 yearsThank 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 over 5 yearsThank 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 over 5 yearsIf 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 over 5 years@Chris, I had missed that part of your requirement. See edit.