What does 's=.*/==' do in sed?
The =
are alternative delimiters. These are used since the pattern contains a /
(which is the more commonly used delimiter). Almost any character can be used as an alternative delimiter, so s@.*/@@
or s_.*/__
would have meant the same thing. With the ordinary delimiter, the sed
expression could have been written as
s/.*\///
(the literal /
that the expression wants to match needs to be escaped here) or, possibly more readable,
s/.*[/]//
(most characters within a [...]
character class are literal1)
What the sed
expression does is to substitute anything that matches .*/
with nothing. This will have the effect of removing everything up to and including the last /
character on the line. It will remove up to the last /
(not the first) since .*
does a greedy match of any sequence of any characters.
Example:
$ echo 'a/b/c' | sed 's/.*[/]//'
c
The unterminated 's' command
error that you get when testing
s798=.*/==/
is due to 7
being used as the delimiter for the s
command. The expression
s7.*/77
would have worked though.
1 ... apart from the characters that have special meaning within [...]
such as ^
(at the start) and -
(when not first, second after ^
, or last). The characters [
and ]
also needs special treatment within [...]
, but that goes outside the scope of this question.
If this is used to get the filename at the end of a path in some string or shell variable, then the basename
utility may do a better job of it (and also does the right thing if the path ends with a slash):
$ basename a/b/c
c
$ basename a/b/c/
c
Likewise, the standard shell parameter substitution ${variable##*/}
would, assuming the variable contains no newlines, be equivalent in its effect to passing the value of $variable
through the above sed
expression in a command substitution, but many times faster.
The variable substitution and the basename
utility also copes with correctly handling pathnames containing newlines, which sed
would not do (since it processes its input line by line).
From https://backreference.org/2010/02/20/using-different-delimiters-in-sed/:
It's a not-so-known fact that sed can use any character as separator for the "s" command. Basically, sed takes whatever follows the "s" as the separator.
So the slash in the middle becomes just a normal character. If I'm interpreting it correctly, your expression:
s=.*/==
could be also be written as:
s/.*\///
and explained as "remove anything before the last slash, including the slash".
It greedily removes all contents before and /
itself.
Example:
echo "nsi/wnx/cmedwcm" | sed 's=.*/=='
Output :
cmedwcm
Here =
serves as the delimiter for regex(.*/) and replacement(null).