Supprimer le numéro de ligne spécifique (s) à partir d'un fichier texte en utilisant sed?

StackOverflow https://stackoverflow.com/questions/2112469

  •  22-09-2019
  •  | 
  •  

Question

Je veux supprimer un ou plusieurs numéros de ligne spécifiques à partir d'un fichier. Comment puis-je faire cela en utilisant sed?

Était-ce utile?

La solution

Si vous voulez supprimer des lignes 5 à 10 et 12:

sed -e '5,10d;12d' file

Cela affichera les résultats à l'écran. Si vous souhaitez enregistrer les résultats dans le même fichier:

sed -i.bak -e '5,10d;12d' file

Ceci sauvegardera le fichier jusqu'à file.bak et supprimer les lignes données.

Remarque: Les numéros de ligne commencent à 1. La première ligne du fichier est 1, de 0

.

Autres conseils

Vous pouvez supprimer une seule ligne particulière avec son numéro de ligne par    sed -i fichier '33d'

Ceci supprimera la ligne 33 sur le numéro de ligne et enregistrez le fichier mis à jour.

et awk ainsi

awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$ 

Ceci est très souvent un symptôme d'un antimodèle. L'outil qui a produit les numéros de ligne pourrait bien être remplacé par un qui supprime les lignes tout de suite. Par exemple;

grep -nh error logfile | cut -d: -f1 | deletelines logfile

(où deletelines est l'utilitaire que vous vous imaginiez besoin) est le même que

grep -v error logfile

Cela dit, si vous êtes dans une situation où vous avez vraiment besoin pour effectuer cette tâche, vous pouvez générer un simple script sed à partir du fichier des numéros de ligne. Humoristiquement (mais peut-être un peu prêter à confusion), vous pouvez le faire avec sed.

sed 's%$%d%' linenumbers

accepte un fichier de numéros de ligne, une par ligne, et produit, sur la sortie standard, les mêmes numéros de ligne avec d ajoutés après chaque. Ceci est un script sed valide, que nous pouvons enregistrer dans un fichier, ou (sur certaines plates-formes) conduit à une autre instance sed:

sed 's%$%d%' linenumbers | sed -f - logfile

Sur certaines plateformes, sed -f ne comprend pas l'argument de l'option - signifie l'entrée standard, donc vous devez rediriger le script dans un fichier temporaire, et nettoyez-le lorsque vous avez terminé, ou remplacer peut-être le tableau de bord seul avec /dev/stdin ou /proc/$pid/fd/1 si votre système d'exploitation (ou shell) a cela.

Comme toujours, vous pouvez ajouter -i avant l'option d'avoir -f sed modifier le fichier cible en place, au lieu de produire le résultat sur la sortie standard. Sur les plates-formes * BSDish (y compris Mac OS X), vous devez fournir un argument explicite à -i ainsi; un idiome commun est de fournir un argument vide; -i ''.

Je voudrais proposer une généralisation avec awk.

Lorsque le fichier est effectuée par blocs de taille fixe et les lignes à supprimer sont répétées pour chaque bloc, awk peut fonctionner correctement de manière

awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print  $0}'
 OriginFile.dat > MyOutputCuttedFile.dat

Dans cet exemple, la taille du bloc est 2000 et je veux imprimer les lignes [1..713] et [1026..1029].

  • NR est la variable utilisée par awk pour stocker le numéro de la ligne actuelle.
  • % donne le reste (ou module) de la division de deux nombres entiers;
  • nl=((NR-1)%BLOCKSIZE)+1 nous écrivons ici dans la variable nl le numéro de ligne à l'intérieur du bloc en cours. (Voir ci-dessous)
  • || et && sont l'opérateur logique ou et .
  • print $0 écrit la ligne complète

Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
  +1   We add again 1 because we want to restore the desired order.

+-----+------+----------+------------+
| NR  | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
|  1  |  1   |    0     |     1      |
|  2  |  2   |    1     |     2      |
|  3  |  0   |    2     |     3      |
|  4  |  1   |    0     |     1      |
+-----+------+----------+------------+

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top