ajouter du texte avec écho sans nouvelle ligne

15

Je veux ajouter du texte au fichier comme echo "abc" >>file.txt.

Mais cet ajout abcaprès une nouvelle ligne

Comment puis-je ajouter abcà la fin du fichier avec écho sans nouvelle ligne?

choijj
la source
2
Le fichier a déjà une nouvelle ligne, vous ajoutez juste après. Vous devrez donc remplacer le caractère de nouvelle ligne de la dernière ligne par «abc».
ctrl-alt-delor
Bienvenue sur StackExchange! Votre question est bonne; il aurait été préférable que vous spécifiiez des exemples du contenu de votre fichier (avant l'ajout, ce que vous obtenez après l'ajout, ce que vous vouliez à la place). Je dis cela parce que l'une des réponses est de savoir comment ajouter abcsans une nouvelle ligne finale, qui (après avoir lu attentivement votre question) ne semble pas être ce que vous voulez.
Loi29

Réponses:

19

echo "abc" >>file.txtmet une nouvelle ligne après abc , pas avant. Si vous vous retrouvez avec abcsa propre ligne, cela signifie que la nouvelle ligne avant abcétait déjà présente dans file.txt.

Notez qu'il est parfaitement normal qu'un fichier texte se termine par une nouvelle ligne. Sous Unix, une ligne se compose d'une séquence de caractères autres que null⁰ ou newline suivie d'une nouvelle ligne. 1 Par conséquent, tout fichier texte non vide se termine par un caractère de nouvelle ligne.

Si vous souhaitez ajouter du texte à la dernière ligne d'un fichier, vous ne pouvez pas le faire avec >>, car cela s'ajoute toujours au fichier, donc il écrit toujours après la dernière nouvelle ligne. Au lieu de cela, vous avez besoin d'un outil capable de modifier un fichier existant. Par exemple, vous pouvez utiliser sed :

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

Dans la commande sed, le premier $signifie « s/REGEX/REPLACEMENT/exécuter la commande suivante uniquement sur la dernière ligne», la commande remplace REGEX par REPLACEMENT et l'expression régulière $correspond à la fin de la ligne.

La commande sed de Linux a une fonction intégrée pour automatiser cette séquence de création de nouveau fichier et de remplacement, vous pouvez donc la raccourcir en

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

C'est un octet nul, que ASCII appelle NUL et Unicode appelle U + 0000. Les programmes de traitement de texte peuvent ou non gérer ce caractère.
1 Voir les définitions de fichier texte , ligne et caractère de nouvelle ligne dans la section "Définitions" du chapitre Définitions de base de IEEE 1003.1-2008: 2016.

Gilles 'SO- arrête d'être méchant'
la source
2
Votre deuxième paragraphe signifie-t-il qu'un fichier qui ne se termine pas par une nouvelle ligne n'est pas un fichier texte? Par exemple, si je prends un fichier texte ASCII existant qui se termine par une nouvelle ligne et que j'ajoute un seul octet 0x41(ASCII 'A'), ce n'est techniquement plus un fichier texte? Si c'est le cas, je suggérerais de souligner ce point car c'est une sorte de définition peu intuitive; sinon, un léger changement de formulation pourrait aider à éviter la confusion.
David Z
2
@DavidZ: C'est la définition standard d'un fichier texte dans Unixland. IIRC est même quelque part dans POSIX.
Kevin
1
@Kevin Intéressant, je n'avais jamais entendu ça auparavant. Eh bien, même si c'est standard, je pense que ce n'est pas intuitif.
David Z
15

Je ne pense pas que ce soit possible avec la echocommande, utilisez sedplutôt l'approche suivante :

sed -i '$ s/$/abc/' file.txt
  • -i- modifier le fichier sur place
  • $ - indiquer le dernier enregistrement / ligne
  • s/$/abc/- remplacer la fin de la ligne $par une sous-chaîne abc(pour le dernier enregistrement)
RomanPerekhrest
la source
2
Notez que «en place» ne signifie pas vraiment en place. Cela signifie "écrire le contenu modifié dans un fichier nommé temporaire à côté du fichier existant et le remplacer". Vous pouvez le prouver en regardant les inodes avecdate >file; ls -i file; sed -i 's/201/ZZZ/' file; ls -i file
roaima
@roaima, je suis au courant que sed change le numéro d'inode.
RomanPerekhrest
2
Je pensais que vous l'auriez été, mais je craignais qu'avec votre accent mis sur place la nuit OP pense qu'il pourrait être utilisé pour éviter une double utilisation d'espace disque, par exemple avec un gros fichier.
roaima
@roaima, la nuit pense -> pourrait penser ...
RomanPerekhrest
13

En supposant que le fichier ne se termine pas déjà par une nouvelle ligne et que vous souhaitez simplement ajouter du texte sans en ajouter un, vous pouvez utiliser l' -nargument, par exemple

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

Cependant, certains systèmes UNIX ne proposent pas cette option; si tel est le cas, vous pouvez utiliser printf, par exemple

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

(l' %sargument initial étant de se prémunir contre le texte supplémentaire %contenant des caractères de mise en forme)

De man echo(sur macOS High Sierra):

-n

N'imprimez pas le caractère de fin de ligne. Cela peut également être réalisé en ajoutant '\c'à la fin de la chaîne, comme cela est fait par les systèmes compatibles iBCS2. Notez que cette option ainsi que l'effet de '\c'sont définis par l'implémentation dans IEEE Std 1003.1-2001 ("POSIX.1") tel que modifié par le Cor. 1-2002. Les applications visant une portabilité maximale sont fortement encouragées à utiliser printf(1)pour supprimer le caractère de nouvelle ligne.

duveteux
la source
Il bien évidemment ne se termine par un saut de ligne. echo -nne mettrait pas de nouvelle ligne à la fin de abc, mais abcserait toujours précédé d'une nouvelle ligne, ce que l'utilisateur veut éviter.
Kusalananda
@Kusalananda Ma réponse était davantage basée sur l'hypothèse que le PO tenterait de changer son processus de telle sorte que les parasites n'apparaissent \npas en premier lieu. Plus d'options sont meilleures, surtout lorsqu'elles n'impliquent pas d'avoir à réécrire le fichier entier chaque fois qu'un changement se produit (ce qui peut devenir assez lent et s'exécuter en temps polynomial s'il est répété).
moelleux
9

Si vous avez la truncatecommande et que votre fichier texte a NL comme dernier caractère, vous pouvez le supprimer puis ajouter votre texte comme ceci:

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

(Notez que truncatele contenu du fichier ne fait rien et, dans cet exemple, réduit simplement la taille du fichier d'un octet. Si votre dernier caractère n'est pas un seul octet, c'est-à-dire qu'il s'agit d'un caractère "large" à plusieurs octets, vous introduirez la corruption.)

roaima
la source
5

Ce que vous voulez, c'est l'ajouter à la fin de la dernière ligne, donc juste avant le délimiteur de cette dernière ligne, donc juste avant le dernier caractère du fichier.

Avec ksh93, vous pouvez faire:

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

1<>est l'opérateur standard pour ouvrir un fichier en mode lecture + écriture (et surtout sans troncature ) sur stdout et >#((...))est un opérateur de recherche spécifique à ksh93 (ici pour rechercher avant le dernier octet). Notez que echoécrit abc<newline>où le aremplace la nouvelle ligne qui était là et echoajoute sa propre nouvelle ligne.

L' zshéquivalent:

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

Bien que pour un équivalent plus exact, vous devrez également imprimer un message d'erreur en cas d'échec de la recherche:

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
la source
-1

Probablement un UUOC mais vous pourriez aussi faire:

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

Comme le souligne Gilles, cette commande est limitée:

Cela fonctionne principalement, mais pas s'il y a parfois une ligne vierge à la fin du fichier et une ligne vierge immédiatement avant. Par exemple, un fichier avec un nombre fixe de lignes, où la dernière ligne est initialement vide et est étendue dans le temps, et l'avant-dernière ligne peut parfois être vide.

Méfiez- catvous également des fichiers que vous ne connaissez pas:

Conclusion :

Utilisez sed

jesse_b
la source
2
Cela fonctionne principalement, mais pas s'il y a parfois une ligne vierge à la fin du fichier et une ligne vierge immédiatement avant. Par exemple, un fichier avec un nombre fixe de lignes, où la dernière ligne est initialement vide et est étendue dans le temps, et l'avant-dernière ligne peut parfois être vide.
Gilles 'SO- arrête d'être méchant'
Dois-je le supprimer? Je pense vraiment que Roman / votre réponse est la bonne voie à suivre, mais je sais que j'aime personnellement voir des alternatives, et OP a demandé echo: p
jesse_b
1
Cela met également le fichier entier sur la ligne de commande
n.caillou
@ n.caillou hein? Cela n'imprimera rien sur STDOUT.
jesse_b
2
Eh bien, aucune de ces vulnérabilités n'est vraiment liée à cat, mais à des problèmes avec des séquences d'échappement arbitraires envoyées au terminal.
ilkkachu