Estoy escribiendo scripts de shell para mi servidor, que es un alojamiento compartido que ejecuta FreeBSD. También quiero poder probarlos localmente, en mi PC con Linux. Por lo tanto, estoy tratando de escribirlos de forma portátil, pero sedno veo forma de hacerlo.
Parte de mi sitio web utiliza archivos HTML estáticos generados, y esta línea de sed inserta DOCTYPE correcto después de cada regeneración:
sed -i '1s/^/<!DOCTYPE html> \n/' ${file_name.html}
Funciona con GNU seden Linux, pero FreeBSD sedespera que el primer argumento después de la -iopción sea una extensión para la copia de seguridad. Así es como se vería:
sed -i '' '1s/^/<!DOCTYPE html> \n/' ${file_name.html}
Sin embargo, GNU seda su vez espera que la expresión siga inmediatamente después -i. (También requiere correcciones con el manejo de nueva línea, pero eso ya se respondió aquí )
Por supuesto, puedo incluir este cambio en la copia del script de mi servidor, pero eso podría causar problemas, es decir, mi uso de VCS para el control de versiones. ¿Hay alguna manera de lograr esto con sed de una manera totalmente portátil?

-iRespuestas:
GNU sed acepta una extensión opcional después
-i. La extensión debe estar en el mismo argumento sin espacio intermedio. Esta sintaxis también funciona en BSD sed.Tenga en cuenta que en BSD,
-itambién cambia el comportamiento cuando hay varios archivos de entrada: se procesan de forma independiente (por ejemplo,$coincide con la última línea de cada archivo). Además, esto no funcionará en BusyBox.Si no desea utilizar archivos de copia de seguridad, puede verificar qué versión de sed está disponible.
O, alternativamente, para evitar golpear los parámetros posicionales, defina una función.
Si no quieres molestarte, usa Perl.
Si desea escribir un script portátil, no lo use
-i, no está en POSIX. Haga manualmente lo que sed hace debajo del capó: es solo una línea más de código.fuente
sed -itambién implica-s. Y la forma más fácil de verificar si hay GNUsedes con elsed vcomando que es un noop válido para GNU pero falla en cualquier otro lugar.sed -i$(sed v < /dev/null 2> /dev/null || echo -n " ''") -e '...' "$file"si no es GNU sed, inserta un espacio seguido de dos comillas después-ipara que trabaja en BSD. GNU sed obtiene solo-i.vcomando para probar GNU sed. ¿Qué pasa si FreeBSD decide implementarlo?sed vdado que ese es su propósito para existir.Si no encuentras un truco para hacer que el
sedjuego sea agradable, puedes intentar:No utilizar
-i:Usa Perl
fuente
ed
Siempre puede usar
edpara anteponer una línea a un archivo existente.Detalles
Los bits alrededor del
<!DOCTYPE html>son comandos paraedindicarle que agregue esa línea al archivomy.html.sed
Creo que este comando
sedtambién se puede usar:fuente
También puede hacer manualmente lo que
perl -ihace debajo del capó:Como
perl -i, no hay copia de seguridad, y como la mayoría de las soluciones dadas aquí, tenga en cuenta que puede afectar los permisos, la propiedad del archivo y puede convertir un enlace simbólico en un archivo normal.Con:
sedsobrescribiría el archivo sobre sí mismo, por lo que no afectaría la propiedad y los permisos o enlaces simbólicos. Funciona con GNUsedporquesednormalmente habrá leído un búfer lleno de datosfile(4k en mi caso) antes de sobrescribirlo con elicomando. Eso no funcionaría si el archivo fuera más de 4k, excepto por el hecho de quesedtambién amortigua su salida.Básicamente
sedfunciona en bloques de 4k para leer y escribir. Si la línea a insertar es más pequeña que 4k,sednunca sobrescribirá un bloque que aún no haya leído.Sin embargo, no contaría con eso.
fuente
echo '<!DOCTYPE html>'o escapar sin "" comillas.FreeBSD sed , que también se usa en Mac OS X, necesita la
-eopción después del-icambio para definir y reconocer el siguiente comando (regex) correctamente y sin ambigüedades.En otras palabras,
sed -i -e ...debería funcionar con FreeBSD y GNUsed.En términos más generales, omitir la extensión de copia de seguridad después de FreeBSD
sed -irequiere algunasedopción explícita o cambiar siguiendo la-ipara evitar confusiones por parte de FreeBSDsedmientras analiza sus argumentos de línea de comandos.(Tenga en cuenta, sin embargo, que las
sedediciones de archivos en el lugar conducen a cambios en el inodo del archivo, consulte la edición "en el lugar" de los archivos ).(Como pista general, las versiones recientes de FreeBSD
sedtienen el-rinterruptor para aumentar la compatibilidad con GNUsed).fuente
bsdsed -i -e 's/a/A/'es una edición en el lugar, se está editando al guardar el original con un sufijo "-e" ( ).testfile.txt-ePara emular
sed -ipara un solo archivo de forma portátil, evitando las condiciones de carrera tanto como sea posible:Por cierto, esto también maneja el posible problema que se
sed -ipresenta, ya que, dependiendo de los permisos de directorio y archivo,sed -ipodría permitir que un usuario sobrescriba un archivo que ese usuario no tiene permisos para editar.También puede hacer copias de seguridad como:
fuente
Puede usar Vim en modo Ex:
1seleccione primera líneaiinsertar texto y nueva líneaxguardar y cerrarO incluso, como en los comentarios, el viejo estándar
ex:fuente
ex, excepto que las implementaciones no son necesarias para admitir varios-cindicadores. Para una portabilidad definitiva, usaríaprintf '%s\n' 1i '<!DOCTYPE html>' . x | ex file