Así que he estado usando 'sed' en Linux por un tiempo, pero he tenido algunas dificultades para tratar de usarlo en OSX ya que 'POSIX sed' y 'GNU sed' tienen tantas pequeñas diferencias. Actualmente estoy luchando con cómo insertar una línea de texto después de un cierto número de línea. (en este caso, línea 4)
En Linux haría algo como esto:
sed --in-place "4 a\ mode '0755'" file.txt
Entonces en OSX probé esto:
sed -i "" "4 a\ mode '0755'" file.txt
Sin embargo, esto sigue dándome un error de 'caracteres adicionales después de \ al final de un comando'. Alguna idea de lo que está mal aquí? ¿Tengo un error tipográfico? ¿O no entiendo otra diferencia entre las versiones de sed?
Respuestas:
Estrictamente hablando, la especificación POSIX para
sed
requiere una nueva línea después dea\
:Esto hace que escribir una sola línea de un poco de dolor, que es probablemente la razón de la siguiente extensión de GNU a la
a
,i
yc
comandos:Por lo tanto, para ser portátil con su
sed
sintaxis, deberá incluir una nueva línea después dea\
alguna manera. La forma más fácil es simplemente insertar una nueva línea citada:(donde
$
y>
son indicaciones de shell). Si encuentra que es un dolor,bash
[1] tiene la$' '
sintaxis de comillas para insertar escapes de estilo C, así que solo use[1] y mksh (r39b +) y algunos depósitos de bourne que no son bash (por ejemplo, / bin / sh en FreeBSD 9+)
fuente
Como se describe en esta respuesta , es útil cuando se utilizan comandos sed como
i
ya
para usar múltiples-e "..."
cláusulas. Se entenderá que cada una de estas cláusulas está separada por líneas nuevas. De lo contrario, los comandosi
ya
son difíciles de usar en scripts sed en línea (están diseñados para usarse en un archivo de scripts sed multilínea invocado mediantesed -f file ...
). Parece que no puede usar la nueva línea implícita introducida al final de una-e
cláusula para separara\
la línea de texto y la que se agregará. Pero puede usarlo para terminar la línea de texto que se agregará.En este caso específico, lo que está tratando de hacer podría lograrse con una sola
-e ...
cláusula. Solo tienes que usar ela
comando correctamente. Según el estándar POSIX,a
debe ir seguido de a\
, luego debe seguir una nueva línea, luego se insertará el resto de la siguiente línea (hasta que se encuentre una nueva línea o el final de la-e
cláusula). Entonces podrías hacer:fuente
GNU sed parece ser mucho más comúnmente usado que POSIX sed, basado en ejemplos / tutoriales que he usado de todos modos.
Descubrí que es mucho más fácil instalar GNU sed en cualquier máquina OSX que use. Si está interesado, la mejor manera de hacerlo es instalarlo a través de Homebrew .
Puede simplemente
$ brew install gnu-sed
, o obtener todas las utilidades comunes de GNU$ brew install coreutils
.Luego, cuando se encuentre con un problema de sintaxis con
date
algún otro programa, simplemente puede usar la versión GNU. Finalmente, decidí que era más fácil usar siempre las versiones de GNU y ponerlas antes que las versiones del sistema en miPATH
.fuente
Perl no sufre de tales idiosincrasias dependientes de GNU frente a no GNU versus "propietarias". Podrías hacerlo:
El
-n' option creates a loop that reads every line of the input file. Unlike its cousin
-p(not used here) it doesn't automatically print every line read. The
-iinvokes in-place replacement. The argument to
-i(viz. ".old") can be dropped or changed. It leaves a backup of the unmodified file. The -e
señala el comienzo del guión.El
$.
denota el número de línea, comenzando con la línea 1. Por lo tanto, la línea de comando lee 'archivo' y cuando el número de línea es igual a 4, imprime esa línea seguida de lo que desee inyectar.Me apresuraría a agregar que Perl debe sus raíces a
sed
AWK y C, por lo que la sintaxis para sustituciones simples, etc. no es una curva de aprendizaje muy empinada.fuente
perl -wlpi.old -e 'print "mode 0755" if $. == 5' file.txt
. El-p
interruptor funciona bien aquí (ya que queremos imprimir cada línea); solo tenemos que cambiar la lógica de "imprimir después de la línea 4" a "imprimir antes de la línea 5". Y el-l
interruptor hace que "\ n" se imprima automáticamente con cadaprint
, para que no tenga que imprimirlo usted mismo.