0

In a php script I have some expressions written as $variable_like_that, $variable_like_other, $variable_this_thing, $variable_like_this ... and I like to find and replace them as undefined variable like this 'variable_like_that', 'variable_like_other', 'variable_this_thing', 'variable_like_this' . They all begin by $variable.

I tried to do something with sed, whose syntax is very strange to the uninitiated:

sed -e "s/$variable_(.*\)/('\)$variable_(.*\)\('\)/g" myscript.php

I know, I'm not very well versed in it yet...

So my questions are:

  • Is sed the right tool for this job?
  • if yes, I will appreciate help to make things right.
  • if not I will appreciate some suggestions.
Daniel Miladinov
  • 1,582
  • 9
  • 20
Olivier
  • 21
  • 1
  • 1

2 Answers2

2

Is sed the right tool for this job?

I think sed is a fine tool for the job you are trying to do. The pattern you tried was close, but had a few things wrong with it:

  • The option swith, -e, and
  • Your substitution command's search/replace pattern.

Which option switch should I use?

Instead of sed -e, which outputs its results to stdout but leaves your file unchanged, you want to use sed -i, to edit the file "in-place", saving the changes it made back to the file. From sed's man page regarding the -i switch:

-i[SUFFIX], --in-place[=SUFFIX]
    edit files in place (makes backup if extension supplied)

What about my substitution command's search/replace pattern?

For the substitution command you send to sed, you want to match strings that begin with $variable and then end with anything else. The search pattern I would use for that is:

\$\(variable\w\+\) 

A few points about that:

  • (We need to escape $ with a \ because by itself $ has a special meaning (end of line))
  • \w is the regular expression pattern that matches any word-like character as well as _
  • \+ means "one or more of the previous pattern"
  • Anything inside escaped parentheses, e.g. \(...\) gets put into a group for either alternating patterns or to be "remembered" for replacement. In our case, we're using them to remember them for replacement.

All together, it basically means, "find strings that begin with $variable and then end with anything else, and remember what you found (minus the dollar sign, since it's not inside the parentheses)."

Next, we need to specify the replacement pattern. Since we have a pattern for what we want to find, we just need to specify what to replace it with:

'\1'

The \1 stands for "the first back-reference", where back-reference is the fancy term for "stuff that matches the first pattern we want to remember (what we put inside the \(\)).

Also note:

  • You can have multiple groups of \(\) in your search pattern; the second would be \2, the third would be \3, etc.
  • \0 is a special back-reference which contains the entire string that matched the search pattern. (In our case, it would also contain the $'s we want to remove.)

Also, we want to replace every occurrence of the search pattern that we find, not just on a single line in the file. That is specified with the g flag, which stands for "global". The substitution command, s, the search pattern, the replacement pattern, and the global flag, are all separated by the slash character, /.

That's it for the substitution command. After that, you pass the name of the file or a shell file pattern as the third argument to sed. Putting this all together, we get:

sed -i "s/\$\(variable\w\+\)/'\1'/g" myscript.php

I threw together my own little version of myscript.php to test and verify that the regex I crafted would do what you need. For your reference, I've included before and after versions:

Before:

<?php
lorem ipsum $variable_like_that 
foo bar $variable_like_other baz
one two three $variable_this_thing four
$variable_like_this five six seven eight
?>

After:

<?php
lorem ipsum 'variable_like_that' 
foo bar 'variable_like_other' baz
one two three 'variable_this_thing' four
'variable_like_this' five six seven eight
?>

For more information, you can also read more here: Sed - An Introduction and Tutorial by Bruce Barnett.

Hope this helps!

Daniel Miladinov
  • 1,582
  • 9
  • 20
0

Need to escape the $ and use \1 on the right to replace what you matched with ()

sed -e "s/\$variable_\([^ ,]*\)/'variable_\1'/g" myscript.php
Tad
  • 934
  • 6
  • 10
  • your regex is good. However, the `-e` switch leaves the original file unchanged, but outputs the results to `stdout`. I believe the asker wanted to have the changes saved back to `myscript.php`. – Daniel Miladinov Dec 03 '12 at 02:53
  • it looks like there is a space appears in the result at the end of the first line: `'variable_like_that '` – Olivier Dec 03 '12 at 13:30
  • I meane with with `sed -e "s/\$variable_\(.*\)/'variable_\1'/g" myscript.php` – Olivier Dec 03 '12 at 13:41
  • @Olivier yep - appears sed * is being greedy and doesn't support non-greedy *? syntax. So you'll need to use Danny's regex or use a newer regex program such as perl. See this SO question for someone asking about sed supporting non-greedy matching http://stackoverflow.com/questions/1103149/non-greedy-regex-matching-in-sed – Tad Dec 03 '12 at 16:27
  • @Olivier I was able to figure out an alternate syntax that looks like it may work - I updated my answer – Tad Dec 03 '12 at 16:34
  • I tested this `$variable_like_that, $variable_like_other, $variable_this_thing, $variable_like_this ` and it became this `'variable_like_that', 'variable_like_other', 'variable_this_thing', 'variable_like_this'` – Tad Dec 03 '12 at 16:35
  • As I can see, you changed `(.*\)` for `([^ ,]*\)` and it works for me too. Tanks a lot Tad. I appreciate. – Olivier Dec 03 '12 at 18:42