Reputation: 12650
Why is this simple replacement with sed
inside bash
not working?
echo '[a](!)' | sed 's/[a](!)/[a]/'
It returns [a](!)
instead of [a]
. But why, given that only three characters need to be escaped in a sed
replacement string?
If I account for the case that additional characters need to be replaced in the regex string and try
echo '[a](!)' | sed 's/\[a\]\(!\)/[a]/'
it is still not working.
Upvotes: 0
Views: 71
Reputation: 1419
man echo
tells that the command echo
display a line of text. So [
and (
with their closing brackets are just text.
If you read man grep
and type there /^\ *Character Classes and Bracket Expressions
and /^\ *Basic vs Extended Regular Expressions
you can read the difference. sed and other tools that use regex interprets this as Character Classes and Bracket Expressions.
You can try this
$ echo '[a](!)' | sed 's/(!)//'
Upvotes: -1
Reputation: 203129
sed uses BREs by default and EREs can be enabled by escaping individual ERE metacharaters or by using the -E
argument. [
and ]
are BRE metacharacters, (
and )
are ERE metacharacters. When you wrote:
echo '[a](!)' | sed 's/\[a\]\(!\)/[a]/'
you were turning the [
and ]
BRE metacharacters into literals, which is good, but you were turning the literal (
and )
into ERE metacharacters, which is bad. This is what you were trying to do:
echo '[a](!)' | sed 's/\[a\](!)/[a]/'
which you'd probably really want to write using a capture group:
echo '[a](!)' | sed 's/\(\[a\]\)(!)/\1/'
to avoid duplicating [a]
on both sides of the substitution. With EREs enabled using the -E
argument that last would be:
echo '[a](!)' | sed -E 's/(\[a\])\(!\)/\1/'
Read the sed man page and a regexp tutorial.
Upvotes: 1
Reputation: 626689
The point is that [a]
in the regex pattern does not match square brackets that form a bracket expression. Escape the first [
for it to be parsed as a literal [
symbol, and your replacement will work:
echo '[a](!)' | sed 's/\[a](!)/[a]/'
^^
See this demo
Upvotes: 3