If you want bulletproof, you probably want something a little more portable than the complicated options above. I would stick to POSIX features of ex
and make it stupid-simple: Just remove the line if it's there (regardless of how many times it's there), add it to the end of the file, then save and exit:
ex -sc 'g/^export PATH=\~\/\.composer\/vendor\/bin:\$PATH$/d
$a
export PATH=~/.composer/vendor/bin:$PATH
.
x' ~/.bashrc
I anchored the regex for added robustness, though I think it's almost impossible to accidentally match this regex. (Anchored means using ^
and $
so the regex will only match if it matches an entire line.)
Note that the +cmd
syntax is not required by POSIX, nor is the common feature of allowing multiple -c
arguments.
There are a multitude of other simple ways to do this. For instance, add the line to the end of the file, then run the last two lines of the file through the external UNIX filter uniq
:
ex -sc '$a
export PATH=~/.composer/vendor/bin:$PATH
.
$-,$!uniq
x' input
This is very very clean and simple, and is also fully POSIX-compliant. It uses the Escape feature of ex
for external text filtering, and the POSIX-specified shell utility uniq
The bottom line is, ex
is designed for in-place file editing and it is by far the most portable way to accomplish that in a non-interactive fashion. It predates even the original vi
, actually—the name vi
is for "visual editor", and the non-visual editor it was built upon was ex
.)
For even greater simplicity (and to reduce it to a single line), use printf
to send the commands to ex
:
printf %s\\n '$a' 'export PATH=~/.composer/vendor/bin:$PATH' . '$-,$!uniq' x | ex input
grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...
(orcat
, for that matter)?ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
export
is a command, so the rest of the line is a shell word, NOT an assignment. Therefore unlike with a variable assignment (that doesn't useexport
), you need double quotes or it will break on whitespace. Also see How to correctly add a path to PATH.