tags:

views:

2731

answers:

5
+3  Q: 

regex in sed

Hi.

I need to use sed to convert all occurences of ##XXX## to ${XXX}. X could be any alphabetic character or '_'. I know that I need to use something like:

's/##/\${/g'

But of course that won't properly, as it will convert ##FOO## to ${FOO${

Any takers? - Don

A: 

Use this:

s/##\([^#]*\)##/${\1}/

BTW, there is no need to escape $ in the right side of the "s" operator.

ADEpt
The [^#] is not an accurate match for a string of "any alphabetic character or '_'".
postfuturist
A: 
sed 's/##\([a-zA-Z_][a-zA-Z_][a-zA-Z_]\)##/${\1}/'

The \(...\) remembers...and is referenced as \1 in the expansion. Use single quotes to save your sanity.

As noted in the comments below this, this can also be contracted to:

sed 's/##\([a-zA-Z_]\{3\}\)##/${\1}/'

This answer assumes that the example wanted exactly three characters matched. There are multiple variations depending on what is in between the hash marks. The key part is remembering part of the matched string.

Jonathan Leffler
You are assuming exactly three characters between the hash marks. Even so, you could collapse that by turning [a-zA-Z_][a-zA-Z_][a-zA-Z_] into [a-zA-Z_]{3} .
postfuturist
Yes ... or '\{3\}',
Jonathan Leffler
And the question does just request 3 'X'; I agree that it could be clearer whether the characters in between can be variable in number.
Jonathan Leffler
+3  A: 

Here's a shot at a better replacement regex:

's/##\([a-zA-Z_]\+\)##/${\1}/g'

Or if you assume exactly three characters :

's/##\([a-zA-Z_]\{3\}\)##/${\1}/g'
postfuturist
You need to escape the \( and \)
You've doubled the close brace }.
wnoise
Fixed those, thanks!
postfuturist
+1  A: 
+ is not a standard operator in sed -- maybe in GNU sed.
Jonathan Leffler
And there was no mention of digits.
Jonathan Leffler
Yes, + is an operator in GNU sed, not maybe.
postfuturist
A: 

echo '##XXX##' | sed "s/^##([^#]*)/##${\1}/g"

echo '##XXX##' | sed "s/^##\([^#]*\)/##$\{\1\}/g"