agregar texto con eco sin nueva línea

15

Quiero agregar texto al archivo como echo "abc" >>file.txt.

Pero esto agrega abcdespués de una nueva línea

¿Cómo puedo agregar abcal final del archivo con echo sin nueva línea?

choijj
fuente
2
El archivo ya tiene una nueva línea, solo está agregando después. Por lo tanto, deberá reemplazar el carácter de nueva línea de la última línea, con "abc".
ctrl-alt-delor
¡Bienvenido a StackExchange! Tu pregunta es buena; hubiera sido mejor si especificaras ejemplos del contenido de tu archivo (antes de la adición, lo que obtienes después de la adición, lo que querías en su lugar). Digo esto porque una de las respuestas es cómo agregar abcsin una nueva línea final, que (después de leer atentamente su pregunta) no parece ser lo que desea.
Ley29

Respuestas:

19

echo "abc" >>file.txtpone una nueva línea después abc , no antes. Si termina abcen su propia línea, eso significa que la nueva línea anterior abcya estaba presente en file.txt.

Tenga en cuenta que es perfectamente normal que un archivo de texto termine en una nueva línea. En Unix, una línea consta de una secuencia de caracteres distintos de nulo⁰ o nueva línea seguida de una nueva línea. 1 Por lo tanto, cualquier archivo de texto no vacío termina con un carácter de nueva línea.

Si desea agregar texto a la última línea de un archivo, no puede hacerlo >>, ya que esto siempre se agrega al archivo, por lo que siempre escribe después de la última línea nueva. En cambio, necesita una herramienta que sea capaz de modificar un archivo existente. Por ejemplo, puede usar sed :

sed '$ s/$/abc/' file.txt >file.txt.new && mv file.txt.new file.txt

En el comando sed, el primero $significa "hacer el siguiente comando solo en la última línea", el comando s/REGEX/REPLACEMENT/reemplaza REGEX por REPLACEMENT, y la expresión regular $coincide al final de la línea.

El comando sed de Linux tiene una característica incorporada para automatizar esta secuencia de crear-nuevo-archivo-y-reemplazar, para que pueda acortar eso a

sed -i '$ s/$/abc/' file.txt

Eso es un byte nulo, que ASCII llama NUL y Unicode llama U + 0000. Los programas de procesamiento de texto pueden o no hacer frente a este personaje.
1 Consulte las definiciones de archivo de texto , línea y carácter de nueva línea en la sección "Definiciones" del capítulo Definiciones básicas de IEEE 1003.1-2008: 2016.

Gilles 'SO- deja de ser malvado'
fuente
2
¿Su segundo párrafo implica que un archivo que no termina con una nueva línea no es un archivo de texto? Por ejemplo, si tomo un archivo de texto ASCII existente que termina con una nueva línea y agrego un solo byte 0x41(ASCII 'A'), ¿técnicamente ya no es un archivo de texto? Si es así, sugeriría enfatizar ese punto ya que es una definición poco intuitiva; de lo contrario, un ligero cambio en la redacción podría ayudar a evitar la confusión.
David Z
2
@DavidZ: Esa es la definición estándar de un archivo de texto en Unixland. IIRC está incluso en POSIX en alguna parte.
Kevin
1
@ Kevin Interesante, nunca había escuchado eso antes. Bueno, incluso si es estándar, creo que es poco intuitivo.
David Z
15

No creo que sea posible con el echocomando, use el siguiente sedenfoque en su lugar:

sed -i '$ s/$/abc/' file.txt
  • -i- modificar el archivo en el lugar
  • $ - indicar el último registro / línea
  • s/$/abc/- sustituya el final de la línea $con subcadena abc(para el último registro)
RomanPerekhrest
fuente
2
Tenga en cuenta que "en el lugar" no significa realmente en el lugar. Significa "escribir el contenido editado en un archivo con nombre temporal junto con el archivo existente y luego reemplazarlo". Puedes probar esto mirando los date >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
inodes
@roaima, estoy al tanto del número de inodo de cambio de sed.
RomanPerekhrest
2
Pensé que lo habrías hecho, pero me preocupaba que, con tu énfasis en el lugar de la noche de OP, creas que podría usarse para evitar el uso de doble espacio en el disco, por ejemplo, con un archivo grande.
roaima
@roaima, noche piensa -> podría pensar ...
RomanPerekhrest
13

Suponiendo que el archivo no termina en una nueva línea y simplemente desea agregar más texto sin agregar uno, puede usar el -nargumento, por ejemplo

echo -n "some text here" >> file.txt

Sin embargo, algunos sistemas UNIX no ofrecen esta opción; si ese es el caso, puede usar printf, por ejemplo

printf %s "some text here" >> file.txt

(el %sargumento inicial es evitar el texto adicional que tiene %caracteres de formato)

Desde man echo(en macOS High Sierra):

-norte

No imprima el carácter de nueva línea final. Esto también se puede lograr agregando '\c'al final de la cadena, como lo hacen los sistemas compatibles con iBCS2. Tenga en cuenta que esta opción, así como el efecto de, '\c'están definidos por la implementación en IEEE Std 1003.1-2001 ("POSIX.1"), tal como fue modificado por Cor. 1-2002. Se recomienda encarecidamente que las aplicaciones destinadas a la máxima portabilidad utilicen printf(1)para suprimir el carácter de nueva línea.

mullido
fuente
Obviamente , termina con una nueva línea. echo -nno pondría una nueva línea al final de abc, pero abcaún estaría precedida por una nueva línea, que es lo que el usuario quiere evitar.
Kusalananda
@Kusalananda Mi respuesta fue más usando la suposición de que el OP trataría de cambiar su proceso de tal manera que lo espurio \nno apareciera en primer lugar. Más opciones son mejores, especialmente cuando no implican tener que reescribir todo el archivo cada vez que ocurre un cambio (que puede volverse bastante lento y ejecutarse en tiempo polinómico si se hace repetidamente).
esponjoso
9

Si tiene el truncatecomando y su archivo de texto tiene NL como último carácter, puede eliminarlo y luego agregar su texto de esta manera:

truncate --size -1 file.txt
echo "abc" >>file.txt

(Tenga en cuenta que truncateno le importa nada el contenido del archivo, y en este ejemplo simplemente reduce el tamaño del archivo en un byte. Si su último carácter no es un solo byte, es decir, es un carácter "ancho" de varios bytes, entonces introducirá corrupción).

roaima
fuente
5

Lo que desea es agregarlo al final de la última línea, justo antes del delimitador de esa última línea, justo antes del último carácter del archivo.

Con ksh93, puedes hacer:

echo abc 1<> file >#((EOF - 1))

¿Dónde 1<>está el operador estándar para abrir un archivo en modo lectura + escritura (y más importante sin truncamiento ) en stdout y >#((...))es un operador de búsqueda específico de ksh93 (aquí para buscar antes del último byte)? Tenga en cuenta que echoescribe abc<newline>donde asobrescribe la nueva línea que estaba allí y echoagrega su propia nueva línea.

El zshequivalente:

zmodload zsh/system
{sysseek -w end -u 1 -1 && echo abc} 1<> file

Aunque para un equivalente más exacto, también necesitaría imprimir un mensaje de error en caso de no buscar:

zmodload zsh/system
if sysseek -w end -u 1 -1; then
  echo abc
else
  syserror -p "$0: $LINENO: seek: "
fi 1<> file
Stéphane Chazelas
fuente
-1

Probablemente un UUOC pero también podrías hacer:

echo "$(cat file.txt)abc" >file.txt

Como Gilles señala, este comando es limitado:

Esto funciona principalmente, pero no si a veces hay una línea en blanco al final del archivo y una línea en blanco inmediatamente antes. Por ejemplo, un archivo con un número fijo de líneas, donde la última línea está inicialmente vacía y se extiende con el tiempo, y la penúltima línea a veces puede estar vacía.

Además, tenga cuidado con catel uso de archivos con los que no está familiarizado:

conclusión :

Usa sed

jesse_b
fuente
2
Esto funciona principalmente, pero no si a veces hay una línea en blanco al final del archivo y una línea en blanco inmediatamente antes. Por ejemplo, un archivo con un número fijo de líneas, donde la última línea está inicialmente vacía y se extiende con el tiempo, y la penúltima línea a veces puede estar vacía.
Gilles 'SO- deja de ser malvado'
¿Debo eliminarlo? Definitivamente creo que Roman / su respuesta es la forma correcta de hacerlo, pero sé que personalmente me gusta ver alternativas, y OP preguntó echo: p
jesse_b
1
También esto pone todo el archivo en la línea de comando
n.caillou
@ n.caillou ¿eh? Esto no imprimirá nada en STDOUT.
jesse_b
2
Bueno, ninguna de esas vulnerabilidades está realmente relacionada catcon problemas de secuencias de escape arbitrarias que se envían al terminal.
ilkkachu