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"exportes 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
exy 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
+cmdPOSIX no requiere la sintaxis ni la característica común de permitir múltiples-cargumentos.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
expara el filtrado de texto externo y la utilidad de shell especificada por POSIXuniqLa conclusión es que
exestá 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 nombrevies 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
printfpara enviar los comandos aex:fuente
Una posible solución es crear una función para hacer eso:
Primero creamos una variable local
l:resque se usará para contar el número de ocurrencias de la línea.Usamos el
globalcomando: cada vez que la línea coincide,l:resse incrementa.Finalmente, si
l:restodaví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 laoque escribimos la línea para agregar.Nota 1 El método que utilicé para establecer el valor de
l:reses 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
:appendno funcionará dentro delif endifbloque 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
mybintexto "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 debashrcy&no contiene/mybin:/entonces:
ACTUALIZACIÓN : Finalmente, podemos hacer un script vim:
chmod 755 e instálelo. Uso:
bashrcfixtenga cuidado: en
\vmodo,=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 -vno saldrá como se esperaba en esta situación. Gracias @joeytwiddle por el consejo.fuente
grep -vque te dé el código de salida que deseas. Pero! grepdebería hacerlo.-vjusto!.-Fpara que dosgrepno interprete los caracteres como expresiones regulares, y 2. Use en-qlugar de redirigir a/dev/null. Vea mi comentario anterior sobre la pregunta .-qy las-Fopciones? Pensé que>/dev/nullera más universal entre las diferentes plataformas (sun vs hp vs Mac OS X vs Ubuntu vs FreeBSD vs ...)