¿Hay un comando Unix para anteponer algunos datos de cadena a un archivo de texto?
Algo como:
prepend "to be prepended" text.txt
unix
command-line
utilities
prepend
Uno dos tres
fuente
fuente
<<(echo "to be prepended") < text.txt | sponge text.txt
Respuestas:
-i
escribe el cambio en su lugar y realiza una copia de seguridad si se proporciona alguna extensión. (En este caso.old
)1s;^;to be prepended;
sustituye el comienzo de la primera línea por la cadena de reemplazo dada, utilizando;
como delimitador de comando.fuente
\n
después de anteponer; dependiendo de sus necesidades Solución ordenadainFile
incluir los directorios en su ruta?\n
. Debería haber leído los comentarios primero. Maldición.'1s;^;my-prepended-line\;\n;'
fuente
git config --get-regex $arg | sed -r 's/\t{3}/\\n/g';
y esto se confunde al convertir el\t
y\n
.echo "to be prepended"$'\n'"$(cat text.txt)"
Proceso de sustitución
Me sorprende que nadie haya mencionado esto.
lo cual es posiblemente más natural que la respuesta aceptada (imprimir algo y colocarlo en un comando de sustitución es lexicográficamente contra-intuitivo).
... y secuestrando lo que Ryan dijo anteriormente, con
sponge
usted no necesita un archivo temporal:EDITAR: Parece que esto no funciona en Bourne Shell
/bin/sh
Here String (solo zsh)
Usando una cadena aquí
<<<
, puede hacer:fuente
<<(echo "to be prepended") < text.txt
y<<< "to be prepended" < text.txt
construcciones no funcionan en bash; requieren zsh.Esta es una posibilidad:
Probablemente no pueda moverse fácilmente por un archivo intermedio.
Alternativas (pueden ser engorrosas con el escape de la carcasa):
fuente
cat <(echo "to be prepended") text.txt > newfile.txt
. Ahora que lo pienso, no estoy seguro de que el mío esté relacionado, así que publicaré una respuesta por separado.Esto funcionará para formar la salida. El - significa entrada estándar, que se proporciona a través de la tubería desde el eco.
Para reescribir el archivo, se requiere un archivo temporal ya que no se puede volver a conectar al archivo de entrada.
fuente
text.txt
como se solicitó, sino que lo muestra en stdout. La salida podría canalizarse a un archivo diferente si eso funciona para el OPPrefiero la respuesta de Adam
Podemos hacer que sea más fácil usar esponja . Ahora no necesitamos crear un archivo temporal y renombrarlo por
fuente
Si es aceptable reemplazar el archivo de entrada:
Nota:
Hacerlo puede tener efectos secundarios inesperados, que pueden reemplazar un enlace simbólico con un archivo normal, terminar con diferentes permisos en el archivo y cambiar la fecha de creación (nacimiento) del archivo.
sed -i
, como en la respuesta del príncipe John Wesley , intenta al menos restaurar los permisos originales, pero también se aplican las otras limitaciones.Aquí hay una alternativa simple que usa un archivo temporal (evita leer todo el archivo de entrada en la memoria como lo hace la solución de shime ):
Usar un comando de grupo (
{ ...; ...; }
) es un poco más eficiente que usar un subshell ((...; ...)
), como en la solución de 0xC0000022L .Las ventajas son:
Es fácil controlar si el nuevo texto debe anteponerse directamente a la primera línea o si debe insertarse como nueva (s) línea (s) (simplemente agregue
\n
elprintf
argumento).A diferencia de la
sed
solución, funciona si el archivo de entrada está vacío (0
bytes).La
sed
solución se puede simplificar si la intención es anteponer una o más líneas enteras al contenido existente (suponiendo que el archivo de entrada no esté vacío):sed
Lai
función de inserta líneas enteras:Con GNU
sed
:Una variante portátil que también funciona con macOS / BSD
sed
:Tenga en cuenta que la nueva línea literal después de la
\
es obligatoria.Si el archivo de entrada debe editarse en su lugar (conservando su inodo con todos sus atributos):
Usando la venerable
ed
utilidad POSIX :Nota:
ed
invariablemente lee el archivo de entrada como un todo en la memoria primero.Para anteponer directamente a la primera línea (como con
sed
, esto no funcionará si el archivo de entrada está completamente vacío (0
bytes)):-s
ed
mensajes de estado suprimidos .ed
como un documento de varias líneas aquí (<<EOF\n...\nEOF
), es decir, a través de stdin ; de manera predeterminada, la expansión de cadenas se realiza en dichos documentos (las variables de shell se interpolan); cita el delimitador de apertura para suprimir eso (por ejemplo,<<'EOF'
).1
convierte la primera línea en la línea actuals
realiza una sustitución de cadena basada en expresiones regulares en la línea actual, como ensed
; puede incluir nuevas líneas literales en el texto de sustitución, pero deben ser\
-escapeadas.w
vuelve a escribir el resultado en el archivo de entrada (para probar, reemplacew
con,p
para imprimir solo el resultado, sin modificar el archivo de entrada).Para anteponer una o más líneas enteras :
Al igual que con
sed
, lai
función agrega invariablemente una nueva línea final al texto que se va a insertar.0 i
hace0
(el comienzo del archivo) la línea actual y comienza el modo de inserción (i
); tenga en cuenta que los números de línea están1
basados en otra cosa ..
en su propia línea.fuente
Probablemente no tenga nada incorporado, pero podría escribir el suyo con bastante facilidad, así:
Algo así al menos ...
fuente
$$
embargo, el uso es insuficiente para el código de producción (ataque de enlace simbólico de Google); pero ciertamente es mejor que un nombre de archivo estático.mktemp
En algunas circunstancias, el texto antepuesto puede estar disponible solo desde stdin. Entonces esta combinación funcionará.
Si desea omitir la
tee
salida, agregue> /dev/null
.fuente
tee
no golpeetext.txt
antes decat
poder leerlo? Creo que no, lo que haría que esta solución fuera peligrosa para la salud del archivo.lenA=1000000; yes a | head -c $lenA > a.txt; lenB=10000; b=$(yes b | head -c $lenB); echo "$b" | cat - a.txt | tee a.txt > /dev/null
. SilenA
es 1000000 (archivo de 1Mb) ylenB
es 10000 (antecedente de texto de 10Kb), el archivo "a.txt" se sobrescribe con 20Kb de letras "b". Esto está totalmente roto. Ahora, si usa texto de 1Mb a.txt y 1Mb para anteponer,tee
entra en un bucle que genera un archivo de 7Gb +, tuve que detener el comando. Por lo tanto, es obvio que el resultado es impredecible para tamaños grandes. No tengo información sobre si debería funcionar en tamaños pequeños.Solución:
Tenga en cuenta que esto es seguro en todo tipo de entradas, porque no hay expansiones. Por ejemplo, si desea anteponer
!@#$%^&*()ugly text\n\t\n
, simplemente funcionará:La última parte que queda por considerar es la eliminación de espacios en blanco al final del archivo durante la sustitución del comando
"$(cat file.txt)"
. Todas las soluciones para esto son relativamente complejas. Si desea conservar las nuevas líneas al final del archivo.txt, consulte esto: https://stackoverflow.com/a/22607352/1091436fuente
file.txt
es más grande de lo que se puede incluir en la lista de argumentosprintf
.Otra forma de usar
sed
:Si la línea a anteponer es multilínea:
fuente
sed -i '1ito be prepended' inFile
, o solo está permitido para GNU sed?sed
, eli
comando va seguido de una barra diagonal inversa y una nueva línea, y cada línea de entrada, excepto la última, también termina con una barra diagonal inversa. GNUsed
permite shorthands a lo largo de las líneas que usted pregunta, pero solo GNUsed
lo hace '.Según lo probado en Bash (en Ubuntu), si comienza con un archivo de prueba a través de;
echo "Original Line" > test_file.txt
puedes ejecutar;
echo "$(echo "New Line"; cat test_file.txt)" > test_file.txt
o, si la versión de bash es demasiado antigua para $ (), puede usar backticks;
echo "`echo "New Line"; cat test_file.txt`" > test_file.txt
y reciba los siguientes contenidos de "test_file.txt";
Sin archivo intermediario, solo bash / echo.
fuente
Otra solución bastante sencilla es:
fuente
cat
expansión del parámetro entre comillas dobles es una muy buena razón para un voto negativo . Este código está dividiendo el contenido del archivo en palabras y pasando cada una de esas palabras como un argumento separado paraecho
. Pierde los límites del argumento original, pierde líneas nuevas / pestañas / etc., y las cadenas como\t
y\n
en el texto original se reemplazan con pestañas y líneas nuevas en lugar de mantenerse como estaban.Si te gusta vi / vim, este puede ser más tu estilo.
fuente
fuente
Recomiendo definir una función y luego importarla y usarla cuando sea necesario.
Luego úsalo así:
El contenido de su archivo será:
Estoy a punto de utilizar este enfoque para implementar un actualizador de registro de cambios.
fuente