Find and replace using regex in sed
Solution 1
You could use +
to enforce at least one character which is not a #
Since the sed
in OSX does not support the enhanced regular expression syntax like +
by default, you need to pass the -E
flag to sed. And the good news is -E
flag works well on *nix
systems too. When using the -E
flag, you can skip escaping the special regex characters like +
, (
, etc.
sed -E "s/#([^#]+)#/===\1===/g" filename
Solution 2
The easiest way is to match the blanks too:
sed 's/# \([^#]*\) #/=== \1 ===/g' filename
Another way is to require multiple (one or more) non-hashes between the two hashes:
sed 's/#\([^#]\{1,\}\)#/===\1===/g' filename
The \{n,m\}
is a quantifier notation that requires at least n occurrences and at most m occurrences of the pattern immediately before it, so it is generalization of the ?
, *
and +
metacharacters (which can be represented by \{0,1\}
, \{0,\}
, and \{1,\}
respectively). If m is missing, it means any number not smaller than n; if n is missing, it means any number not larger than m, and so is equivalent to 0. In my example, I'm using it as the classic, portable (to prehistoric versions of sed
off Linux and Mac OS X) version of +
.
Another way of writing that is:
sed 's/#\([^#][^#]*\)#/===\1===/g' filename
And you can combine the ideas, of course:
sed 's/# \([^#][^#]*\) #/=== \1 ===/g' filename
sed 's/# \([^#]\{1,\}\) #/=== \1 ===/g' filename
Sudar
I am a developer from Chennai, India, mostly interested in WordPress, Android and Arduino programming. I write about my projects at my blog. You can also checkout my code that I have released as open source in my github account. You can follow me on twitter.
Updated on June 04, 2022Comments
-
Sudar almost 2 years
I want to replace
# Bulk Delete #
with
=== Bulk Delete ===
I am using the following
sed
command.sed "s/#\([^#]*\)#/===\1===/g" filename
It works, but it also replaces
### Translation
with
======# Translation
How to prevent it and make it work in both mac and ubuntu?
-
Tuxdude about 11 years@JonathanLeffler - updated the answer. Try with the
-E -e
flag, should work on bothOSX
and*nix
-
Jonathan Leffler about 11 yearsThe
-e
option universally (meaning all versions ofsed
) specifies that the next argument is part of the script; you can specify it multiple times to build up a complex script. On Mac OS X, you can use the-E
option to invoke 'extended regular expressions', but then you don't need the backslashes:sed -E -e 's/#([^#]+#/===\1===/g'
. -
Tuxdude about 11 yearsYes you're right about,
-e
which was optional. Should have mentioned that. -
Jonathan Leffler about 11 yearsOK—we're in agreement on Mac. I'm not sure about elsewhere. According to its help message, GNU
sed
(4.4.2) uses the-r
option to invoke extended regular expressions. However, it seems to support-E
as an undocumented synonym for-r
. -
Tuxdude about 11 yearsI tried it on my Linux box with
GNU sed version 4.2.1
and it seems to be happy with-E
. And yes you're right-r
seems to be the option documented in the man page and I do not see-E
. I'm not sure if the man page on my system is outdated. -
Sudar about 11 yearsI knew about the
-r
option, but didn't know about-E
. Thanks for mentioning it. -
Sudar about 11 yearsCan you kindly explain
's/#\([^#]\{1,\}\)#/===\1===/g'
a bit more, or point me to some documentation? I am slightly confused. -
Sudar about 11 yearsThank you for the explanation