Comment puis-je éditer les n dernières lignes d'un file?

Y at-il une command qui me permettra d'éditer les n dernières lignes dans un file? J'ai plusieurs files, qui ont tous un nombre différent de lignes à l'intérieur. Mais je voudrais modifier les n dernières lignes dans chaque file. Le but est de replace les virgules par des points-virgules dans les n dernières lignes. Mais seulement dans les dernières n dernières lignes.

Je ne veux supprimer aucune ligne, je veux juste replace chaque virgule par un point-virgule dans les n dernières lignes de chaque file.

En utilisant la command sed je suis en mesure de replace la dernière ligne avec cette command. Comme décrit ici: Comment puis-je supprimer du text sur la dernière ligne d'un file?

Mais cela ne me permet que de modifier la toute dernière ligne, et non le dernier nombre de lignes.

Pour replace les virgules par des points-virgules sur les n dernières lignes avec ed :

 n=3 ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq' 

Séparer cela:

  • ed -s = exécuté en mode silencieux (ne pas signaler les octets écrits à la fin)
  • '$-' = à partir de la fin du file ( $ ) less …
  • $((n-1)) = n-1 lignes …
  • ( $' ... ' = citer le rest de la command pour le protéger du shell)
  • ,$s/,/;/g = … jusqu'à la fin du file ( ,$ ), searchz et remplacez toutes les virgules par des points-virgules.
  • \nwq = termine la command précédente, puis sauvegarde et quitte

Pour replace les virgules par des points-virgules sur les n dernières lignes avec sed :

 n=3 sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input 

Briser ça:

  • -i = éditer le file "in-place"
  • $(( ... )) = faire des maths:
  • $( wc -l < input) = get le nombre de lignes dans le file
  • -n + 1 = revenir en arrière n-1 lignes
  • ,\$ = de n-1 lignes jusqu'à la fin du file:
  • s/,/;/g = replace les virgules par des points-virgules.

Solution utilisant tac et sed pour replace chaque virgule par un point-virgule dans les 50 dernières lignes de file.txt:

 tac file.txt | sed '1,50s/,/;/g' | tac 

Avec la head GNU et un shell Bourne-like:

 n=20 { head -n -"$n"; tr , ';'; } < file 1<> file 

Nous écrasons le file sur lui-même. C'est OK pour une translittération d'octets à octets mais pas nécessairement si la modification implique la modification de la taille du file (dans ce cas, vous voudriez replace 1<> file par > other-file && mv other-file file par exemple).

Supposons que nous voulons replace les 7 dernières lignes de la séquence suivante par le script shell et l'implémentation GNU de sed :

 $ seq 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 

Étape 1 : permet d'get le numéro de la dernière ligne de la séquence comme suit. Jetez un oeil à ceci et cela :

 $ lastLine=`seq 20|sed -n '$='` $ echo $lastLine 20 

Étape 2 : permet de définir le nombre de lignes (à la fin de la séquence) que nous avons l'intention de modifier:

 $ numberOfLines=7 $ echo $numberOfLines 7 

Étape 3 : permet de calculer la ligne de départ en fonction des variables précédentes, comme suit. Jetez un oeil à ceci :

 $ startLine=`expr $lastLine - $numberOfLines + 1` $ echo $startLine 14 

Étape 4 : Maintenant, nous pouvons replace les 7 dernières lignes de séquence par quelque chose d'autre, comme suit. Jetez un oeil à ceci :

 $ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}" 1 2 3 4 5 6 7 8 9 10 11 12 13 WoW4 WoW5 WoW6 WoW7 WoW8 WoW9 WoW0 

L'étape 4 utilise la section 4.4 de la page sed man qui dit:

 'ADDR1,+N' Matches ADDR1 and the N lines following ADDR1. 

L'étape 4, utilise également des guillemets doubles comme mentionné ici .


Eh bien, les 4 étapes sont inutiles si nous utilisons la réponse de Gohu comme ceci:

 $ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac 1 2 3 4 5 6 7 8 9 10 11 12 13 WoW4 WoW5 WoW6 WoW7 WoW8 WoW9 WoW0 

Utilisez la tail et la pipe pour sed:

tail -n 20 file | sed 's/,/;/g'

Cela fonctionne sur le file pour les 20 dernières lignes. Si vous voulez avoir thee canges directement à l'utilisation du file:

tail -n 20 file | sed -i 's/,/;/g'