Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sed replace hyphen with underscore

Tags:

regex

replace

sed

new to regex and have a problem. I want to replace hyphens with underscores in certain places in a file. To simplify things, let's say I want to replace the first hyphen. Here's an example "file":

dont-touch-these-hyphens
leaf replace-these-hyphens

I want to replace hyphens in all lines found by

grep -P "leaf \w+-" file

I tried

sed -i 's/leaf \(\w+\)-/leaf \1_/g' file

but nothing happens (wrong replacement would have been better than nothing). I've tried a few tweaks but still nothing. Again, I'm new to this so I figure the above "should basically work". What's wrong with it, and how do I get what I want? Thanks.

like image 528
Erik Vesterlund Avatar asked Sep 02 '25 16:09

Erik Vesterlund


2 Answers

You can simplify things by using two distinct regex's ; one for matching the lines that need processing, and one for matching what must be modified.

You can try something like this:

$ sed '/^leaf/ s/-/_/' file
dont-touch-these-hyphens
leaf replace_these-hyphens
like image 152
damienfrancois Avatar answered Sep 04 '25 06:09

damienfrancois


Just use awk:

$ awk '$1=="leaf"{ sub(/-/,"_",$2) } 1' file
dont-touch-these-hyphens
leaf replace_these-hyphens

It gives you much more precise control over what you're matching (e.g. the above is doing a string instead of regexp comparison on "leaf" and so would work even if that string contained regexp metacharacters like . or *) and what you're replacing (e.g. the above only does the replacement in the text AFTER leaf and so would continue to work even if leaf itself contained -s):

$ cat file
dont-touch-these-hyphens
leaf-foo.*bar replace-these-hyphens
leaf-foobar dont-replace-these-hyphens

Correct output:

$ awk '$1=="leaf-foo.*bar"{ sub(/-/,"_",$2) } 1' file
dont-touch-these-hyphens
leaf-foo.*bar replace_these-hyphens
leaf-foobar dont-replace-these-hyphens

Wrong output:

$ sed '/^leaf-foo.*bar/ s/-/_/' file
dont-touch-these-hyphens
leaf_foo.*bar replace-these-hyphens
leaf_foobar dont-replace-these-hyphens

(note the "-" in leaf-foo being replaced by "_" in each of the last 2 lines, including the one that does not start with the string "leaf-foo.*bar").

That awk script will work as-is using any awk on any UNIX box.

like image 29
Ed Morton Avatar answered Sep 04 '25 07:09

Ed Morton