Me gustaría editar un archivo en el lugar agregando una línea, solo si aún no existe para que mi script sea a prueba de balas.
Normalmente haría algo como:
cat >> ~/.bashrc <<EOF
export PATH=~/.composer/vendor/bin:\$PATH
EOF
También es posible hacerlo a través de ansible ( line
+ insertafter=EOF
+ regexp
), pero es otra historia.
En vi / ex podría hacer algo como:
ex +'$s@$@\rexport PATH=\~/.composer/vendor/bin:$PATH@' -cwq ~/.bashrc
pero entonces, ¿cómo puedo verificar si la línea ya está allí (y, por lo tanto, no hacer nada) idealmente sin repetir la misma línea?
¿O tal vez hay alguna manera más fácil de hacerlo en Ex editor?
substitute
ex-command
kenorb
fuente
fuente
grep -Fq 'export PATH=~/.composer/vendor/bin:$PATH' ~/.bashrc || ex ...
(ocat
, para el caso)?ex ~/.bashrc -c "if search('export PATH=\~\/.composer\/vendor\/bin:\$PATH')>0 | norm quit | endif | norm Aexport PATH=~/.composer/vendor/bin:$PATH"
export
es un comando , por lo que el resto de la línea es una palabra de shell, NO una asignación. Por lo tanto, a diferencia de una asignación variable (que no usaexport
), necesita comillas dobles o se romperá en espacios en blanco . Consulte también Cómo agregar correctamente una ruta a PATH .Respuestas:
Si quieres a prueba de balas , probablemente quieras algo un poco más portátil que las complicadas opciones anteriores. Me apegaría a las características de POSIX
ex
y lo haría estúpidamente simple: simplemente elimine la línea si está allí (independientemente de cuántas veces esté allí), agréguela al final del archivo, luego guarde y salga:Anclé la expresión regular para mayor robustez, aunque creo que es casi imposible hacer coincidir accidentalmente esta expresión regular. (Anclado significa usar
^
y,$
por lo tanto, la expresión regular solo coincidirá si coincide con una línea completa ).Tenga en cuenta que
+cmd
POSIX no requiere la sintaxis ni la característica común de permitir múltiples-c
argumentos.Hay una multitud de otras formas simples de hacer esto. Por ejemplo, agregue la línea al final del archivo, luego ejecute las dos últimas líneas del archivo a través del filtro externo UNIX
uniq
:Esto es muy, muy limpio y simple, y también es totalmente compatible con POSIX. Utiliza la función de escape
ex
para el filtrado de texto externo y la utilidad de shell especificada por POSIXuniq
La conclusión es que
ex
está diseñada para la edición de archivos en el lugar y es, con mucho, la forma más portátil de lograrlo de una manera no interactiva. Es anterior incluso al originalvi
, en realidad, el nombrevi
es para "editor visual", y el editor no visual sobre el que se creó fueex
).Para una simplicidad aún mayor (y para reducirlo a una sola línea), use
printf
para enviar los comandos aex
:fuente
Una posible solución es crear una función para hacer eso:
Primero creamos una variable local
l:res
que se usará para contar el número de ocurrencias de la línea.Usamos el
global
comando: cada vez que la línea coincide,l:res
se incrementa.Finalmente, si
l:res
todavía es 0, significa que la línea no aparece en el archivo, así que vamos a la última línea graciasG
, y creamos una nueva línea con lao
que escribimos la línea para agregar.Nota 1 El método que utilicé para establecer el valor de
l:res
es un poco pesado y podría ser reemplazado por el sugerido por @Alex en su respuesta con algo como:Nota 2 También para hacer que la función sea más flexible, puede usar argumentos:
escape()
para agregar un\
delante de los caracteres que podría causar un problema en la búsqueda.Tenga en cuenta también que aún tendrá que escapar
\
por sí mismo cuando llame a la función (no logré escapar\
automáticamente):fuente
Tratar:
Tenga en cuenta que
:append
no funcionará dentro delif endif
bloque con el modo Ex (vea VimDoc ), así que tengo que ponerlonorm A...
afuera.fuente
Normalmente uso:
fuente
Para simplificar y evitar la presencia de muchos
\
, la línea que se agregará seráexport PATH=mybin:PATH
.Estrategia principal: sustituir el
mybin
texto "no " (todo el archivo) con texto + definición de ruta-mybin:o con sangría más didáctica :
Si tenemos un partido:
&
tiene el texto completo debashrc
y&
no contiene/mybin:/
entonces:
ACTUALIZACIÓN : Finalmente, podemos hacer un script vim:
chmod 755 e instálelo. Uso:
bashrcfix
tenga cuidado: en
\v
modo,=
significa opcionalfuente
La mayoría de estas respuestas parecen complicadas, ¿qué hay de los buenos y viejos comandos de shell?
Esto podría ser fácilmente una función Bash:
EDITAR : El código de salida de grep es importante y, en este caso, debe invertirse
! grep
;grep -v
no saldrá como se esperaba en esta situación. Gracias @joeytwiddle por el consejo.fuente
grep -v
que te dé el código de salida que deseas. Pero! grep
debería hacerlo.-v
justo!
.-F
para que dosgrep
no interprete los caracteres como expresiones regulares, y 2. Use en-q
lugar de redirigir a/dev/null
. Vea mi comentario anterior sobre la pregunta .-q
y las-F
opciones? Pensé que>/dev/null
era más universal entre las diferentes plataformas (sun vs hp vs Mac OS X vs Ubuntu vs FreeBSD vs ...)