views:

418

answers:

7

How can I use sed to replace this line

char * path_list_[1] = { "/some/random/path" };

with this line

char * path_list_[2] = { "lib/foo", "lib/bar" };

in a file named source.c

Notes:
* The path is really random.
* Your solution should only change this line in source.c
* I'm only interested in a sed oneliner.

You can use this Python regex as a starting point:

text = re.sub('static const char \* path_list_\[1\] = \{ "[^"]*" \};', 
    'static const char * path_list_[2] = { "lib/sun", "lib/matlab" };', text)
+1  A: 

Try this:

sed -e 's/=\s*{\s*"[^"]*"\s*};/= { "lib\/foo", "lib\/bar"};/' source.c | sed -e 's/path_list_\[1\]/path_list_[2]/'
codaddict
@compie: Yes, sed does support negation in char class. I've updated my answer.
codaddict
This solution matches too many lines. The input file contains a lot of other C code.
compie
@compie: can you please show me some lines that are being replaced falsely.
codaddict
+1  A: 

First, find a character that will not appear in your path or your replacement (in general # is a good first approximation, but...).

Then:

sed 's#_.1. = {[^}]*}#_[2] = { "your/first", "and/your/second" }#'

Note that the first character after the s is your separator, there is no requirement for it to be /, it's just traditionally "the character I won't need".

EDIT: Seems as if sed doesn't understand + as "one or more". Use * (zero or more) instead.

Vatine
It doesn't work:echo 'char * path_list_[1] = { "/some/random/path };' | sed 's#_.1. = {[^}]+}#_[2] = { "your/first", "and/your/second" }#'Nothing is replaced.
compie
Sed do understand `+`, but you should either write `\+` instead of `+`, or supply `-r` key.
ZyX
+2  A: 
$ cat file
aaaa
char * path_list_[1] = { "/some/random/path" };
zzzz

$ sed '/char/s@1\]@2]@;s@{.*}.*$@{\"lib\/foo", "lib\/bar"}@' file
aaaa
char * path_list_[2] = {"lib/foo", "lib/bar"}
zzzz
ghostdog74
It is a sed oneliner...the other text is just demonstration.
Broam
It works, but a line like struct = { "value" }; is also replaced.
compie
then you should show more examples of the strings and the format that you need to parse. In your sample text, you don't have `struct`.
ghostdog74
+1  A: 

Assuming that you want to replace string variables named path_list_, and only those.

sed '/path_list_/s@1\]@2]@; /path_list_.*\[.*{/s@\".*\"@\"lib\/foo", "lib\/bar"@'

This replaces only the first 2 lines from the following input.

char * path_list_[1] = { "/some/random/path" };
char * path_list_[1] = {"/some/random/path"};
char * not_replaced[1] = { "/some/random/path" };
char * not_replaced[1] = {"/some/random/path"};
char * path_list_ = {"/some/random/path"};
path_list_[1] = "/some/random/path";
Lachlan Roche
+1  A: 

Based on the Python regex you gave:

echo 'char * path_list_[1] = { "/some/random/path" };' | \
    sed -E -e 's/char \* path_list_\[1\] = \{ "[^"]*" \};/char * path_list_[2] = { "lib\/sun", "lib\/matlab" };/'

outputs

char * path_list_[2] = { "lib/sun", "lib/matlab" };

or alternately

echo 'static const char * path_list_[1] = { "/some/random/path" };' | \
    sed -E -e 's/static const char \* path_list_\[1\] = \{ "[^"]*" \};/static const char * path_list_[2] = { "lib\/sun", "lib\/matlab" };/'

outputs

static const char * path_list_[2] = { "lib/sun", "lib/matlab" };

(This is done using the FreeBSD-type sed included in Mac OS X.)

Isaac
A: 
sed -e 's@char \* path_list_\[1\] = { "[^"]*" };@char * path_list_[2] = { "lib/foo", "lib/bar" };@g'
Alok
A: 
sed -re 's/^(char \* path_list_\[)1(\] = \{ ")[^"]*(" \})\W*$/\12\2\/lib\/foo", "\/lib\/bar\3/' source.c
bpedro