tl,dr:
Use:
sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg
A few comments on your attempted Sed command:
sed -i '/../../../Plumed.h/c\/usr/local/include/Plumed.h' ../dist0.xvg
-i
is not portable, so it appears you are using GNU Sed.
BSD Sed has a -i
switch as well, but the backup extension is a required argument, so to modify a file without saving a backup in BSD Sed requires -i ''
.
Other versions of Sed may have no -i
switch at all.
The regex here, /../../../Plumed.h/
, contains multiple copies of the regex delimiter.
The usual solution to this is to escape the delimiter:
/..\/..\/..\/Plumed.h/
However, there is a little-known fact about Sed, that you can use any character for the regex delimiter (not just in the s
command) if you backslash-escape the first instance. (Well, almost any—backslash or newline not allowed.)
To quote the POSIX specifications directly:
In a context address, the construction "\cBREc
", where c is any character other than <backslash>
or <newline>
, shall be identical to "/BRE/
". If the character designated by c appears following a <backslash>
, then it shall be considered to be that literal character, which shall not terminate the BRE. For example, in the context address "\xabc\xdefx
", the second x stands for itself, so that the BRE is "abcxdef
".
So to avoid the "leaning toothpicks syndrome," note that the following two regexes are equivalent:
/..\/..\/..\/Plumed.h/
\:../../../Plumed.h:
Note that I said "equivalent," not correct. This brings me to my next point, missed in every other answer:
A period (.
) in a regex stands for any character.
If you want to match only a literal period, you can either escape your period with a backslash, or stick it into a character class as in [.]
.
Thus to match only literal periods, the regex should actually be more like:
\:\.\./\.\./\.\./Plumed\.h:
So much for avoiding leaning toothpicks.
You can also use the arguably more readable form:
\:[.][.]/[.][.]/[.][.]/Plumed[.]h:
The c
command changes the entire line, not just the portion of the line matched by the regex.
Use the s
command to only change a portion of a line.
Notably, with the s
command, you don't have to escape your first regex delimiter (even for an unusual character used as a delimiter) the way you do when using an alternate delimiter in an address.
Also, regarding the c
command, it's worth knowing that including the new text on the same line as the c\
is a GNU extension and not portable.
Putting all this together, you can either use the s
command like so:
sed -i 's:"\.\./\.\./\.\./Plumed\.h":"/usr/local/include/Plumed.h":g' ../dist0.xvg
Or, if you want to be even more explicit, you can use an anchored regex and the c
hange command to change the whole line only:
sed -i '\:^#include "\.\./\.\./\.\./Plumed\.h"$:c\#include "/usr/local/include/Plumed.h"' ../dist0.xvg