¿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.txtRespuestas:
-iescribe 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
\ndespués de anteponer; dependiendo de sus necesidades Solución ordenadainFileincluir 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\ty\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
spongeusted no necesita un archivo temporal:EDITAR: Parece que esto no funciona en Bourne Shell
/bin/shHere String (solo zsh)
Usando una cadena aquí
<<<, puede hacer:fuente
<<(echo "to be prepended") < text.txty<<< "to be prepended" < text.txtconstrucciones 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.txtcomo 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
\nelprintfargumento).A diferencia de la
sedsolución, funciona si el archivo de entrada está vacío (0bytes).La
sedsolució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):sedLaifunció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
edutilidad POSIX :Nota:
edinvariablemente 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 (0bytes)):-sedmensajes de estado suprimidos .edcomo 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').1convierte la primera línea en la línea actualsrealiza 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.wvuelve a escribir el resultado en el archivo de entrada (para probar, reemplacewcon,ppara imprimir solo el resultado, sin modificar el archivo de entrada).Para anteponer una o más líneas enteras :
Al igual que con
sed, laifunción agrega invariablemente una nueva línea final al texto que se va a insertar.0 ihace0(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án1basados 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.mktempEn algunas circunstancias, el texto antepuesto puede estar disponible solo desde stdin. Entonces esta combinación funcionará.
Si desea omitir la
teesalida, agregue> /dev/null.fuente
teeno golpeetext.txtantes decatpoder 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. SilenAes 1000000 (archivo de 1Mb) ylenBes 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,teeentra 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.txtes 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, elicomando 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. GNUsedpermite shorthands a lo largo de las líneas que usted pregunta, pero solo GNUsedlo 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.txtpuedes ejecutar;
echo "$(echo "New Line"; cat test_file.txt)" > test_file.txto, si la versión de bash es demasiado antigua para $ (), puede usar backticks;
echo "`echo "New Line"; cat test_file.txt`" > test_file.txty reciba los siguientes contenidos de "test_file.txt";
Sin archivo intermediario, solo bash / echo.
fuente
Otra solución bastante sencilla es:
fuente
catexpansió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\ty\nen 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