Lalle
Lalle

Reputation: 732

Replace all strings in file, using wildcards in the substitution

I'm using sed in bash to try replace all strings matching:

compile 'com.test.*:*'

with:

compile 'com.test.*:+'

Where * is a wildcard.

My file looks like this, it's called moo.txt:

compile 'com.test.common:4.0.1'
compile 'com.test.streaming:5.0.10'
compile 'com.test.ui:1.0.7'

and I want it to look like this:

compile 'com.test.common:+'
compile 'com.test.streaming:+'
compile 'com.test.ui:+'

I've tried to use sed like:

sed -i -- "s/compile \'com.test.*:.*\'/compile \'com.test.*:+\'/g" moo.txt

But this makes the file look like:

compile 'com.test.*:+'
compile 'com.test.*:+'
compile 'com.test.*:+'

Any ideas how to use the wildcard in the substitute field properly?

Upvotes: 2

Views: 1609

Answers (2)

Sundeep
Sundeep

Reputation: 23677

$ sed -E "s/[^:]+$/+'/" moo.txt 
compile 'com.test.common:+'
compile 'com.test.streaming:+'
compile 'com.test.ui:+'
  • [^:]+$ matches all characters other than : at end of line
  • If hex escapes are allowed, use sed -E 's/[^:]+$/+\x27/' to avoid possibility of shell interpretation when using double quotes

To qualify only lines have compile 'com.test at start of line

sed -E "/^compile 'com.test/ s/[^:]+$/+'/" moo.txt

Upvotes: 1

fedorqui
fedorqui

Reputation: 290025

You are matching things after com.test but you don't print them back properly.

So you are indeed matching something, only that you are not printing it back. Instead, you are printing a literal .*:

sed "s/compile \'com.test.*:.*\'/compile \'com.test.*:+\'/g"
#                        ^^                        ^^
#                match this                  print back? NO

To do so, capture the pattern and print it back using a backreference.

sed -E "s/compile 'com.test(.*):.*'/compile 'com.test\1:+'/g"
#                          ^^^^                      ^^
#                    catch this             print back! now YES!

See we are repeating "compile..." too much? This means that we can extend the capture to the very beginning of the line, since the backreference will print all of it back:

sed -E "s/^(compile 'com.test.*):.*'/\1:+'/g"
#          ^^^^^^^^^^^^^^^^^^^^^     ^^
#           capture all of this      print it back

Note the usage of -E to allow sed capture groups with just (...). If we didn't use -E, we should do \(...\).

Note also that you were escaping single quotes, while it is not necessary since you are inside double quotes.

Upvotes: 2

Related Questions