Comment trouver des lignes correspondant à un motif et les supprimer?

14

Dans un fichier avec beaucoup de lignes, je veux supprimer les lignes commençant par HERE IT IS.

Comment puis-je faire cela en utilisant uniquement des outils de ligne de commande?

micgeronimo
la source
2
Bien qu'un peu non conventionnel, vous pourriez utiliser vimcomme ceci vim '+g/^HERE IT IS/d' +wq test.txt
:;
@ Doorknob, merci de l'avoir signalé. En fait, je suis sur le point d'utiliser vim
micgeronimo

Réponses:

28

Essayez sed:

sed -i '/^HERE IT IS/d' <file>

AVERTISSEMENT: il est préférable d'effectuer une sauvegarde lors de l'utilisation d'un -icommutateur de sed:

sed -i.bak '/^HERE IT IS/d' <file>

Le fichier d'origine restera tel que <file>.baket le fichier modifié sera <file>.

heemayl
la source
Comment puis-je mettre un caractère de nouvelle ligne après la chaîne correspondante et écrire sur la nouvelle ligne?
micgeronimo
2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
heemayl
1
@micgeronimo: heureux de vous aider. Vérifiez mes modifications s'il vous plaît.
heemayl
6
@micgeronimo essayez de poser la question à laquelle vous voulez vraiment répondre dans votre question d'origine (rappelez-vous que vous pouvez la modifier), plutôt que par le biais de commentaires qui pourraient être nettoyés / supprimés. Vous pouvez utiliser sed '/^HERE IT IS/G' file.
steeldriver
1
L'utilisation de Sed est tellement pro.
LakshyaAg
18

En plus de la très bonne grepet les sedréponses que vous avez reçu, voici quelques autres outils qui peuvent faire la même chose:

  • Quelques façons Perl:

    perl -ne '/^HERE IT IS/ || print' file > newfile
    perl -ne 'print if !/^HERE IT IS/' file > newfile
    perl -ne 'print unless /^HERE IT IS/' file > newfile
    

    Vous pouvez ajouter le -icommutateur à l'un des exemples pour modifier le fichier en place:

    perl -i.bak -ne '/^HERE IT IS/ || print' file        
    
  • (rester bouche bée

    awk '!/^HERE IT IS/' file > newfile
    

    Les versions plus récentes (4.1.1 et ultérieures) de GNU awk(par défaut awksous Linux) peuvent également modifier le fichier en place:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, probablement d' autres). C'est assez idiot cependant, cela peut être fait mais d'autres outils sont meilleurs.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    
terdon
la source
1
Vous vous montrez juste! ;-) (mais vous avez obtenu un vote positif, car il est intelligent et j'ai beaucoup appris et bashcelui m'a fait LOL)
Fabby
le bash qu'il faut utiliser printf "%s\n" "$line": en citant $ line pour préserver les espaces blancs et en évitant certains problèmes d'écho (interprétation de caractères spéciaux, etc.). et évite la nécessité d'ajouter --aussi.
Olivier Dulac
@OlivierDulac assez juste. Je ne voulais pas compliquer les choses pour les cas marginaux mais depuis que Cuanglm a ajouté IFS=et -r, je peux aussi bien aller jusqu'au bout et le rendre robuste.
terdon
@terdon: tout est pour le bien de tous ^^ (et je l'ai déjà fait +1, car c'est très instructif pour les débutants)
Olivier Dulac
2
@OlivierDulac Je peux vous assurer que si je publiais sur Unix et Linux, j'aurais utilisé printf, IFS =, -r et en citant :). Je simplifie souvent les choses pour le public de l'UA qui est souvent moins à l'aise avec la ligne de commande.
terdon
13

J'utiliserais greppour les filtrer. Par exemple :

grep -v "^HERE IT IS" infile > outfile

Ensuite, déplacez le fichier externe vers le fichier inférieur.

Ben Hills
la source
Pensée intelligente
Anwar
5

sed est définitivement la voie à suivre.

Cette légère modification de la commande que @heemayl vous a donnée supprimera la ligne, que le même cas soit utilisé dans le modèle ou non, en raison du I dans la référence du modèle.

sed -i '/HERE IT IS/Id' <file>

Si vous aviez plusieurs fichiers dans un répertoire sur lequel vous vouliez le faire, vous pouvez le combiner avec find like so.

find . -maxdepth 1 -type f -exec sed -i.bak '/HERE IT IS/Id' {} +

L'option maxdepth signifie que cela ne se reproduira pas dans les répertoires.

Arronical
la source
4

Une autre option python:

#!/usr/bin/env python3
[print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]

Où f est le chemin d'accès au fichier, entre guillemets.

Jacob Vlijm
la source
4

Grep

grep -P '^(?!HERE IT IS)' file

(?!HERE IT IS)assertion d'anticipation négative qui fait que le moteur d'expression régulière ne correspond à toutes les limites de début de ligne ( qui sont généralement mises en correspondance par^ ) que s'il n'est pas suivi par la chaîneHERE IT IS

python

#!/usr/bin/python3
import sys
fil = sys.argv[1]
with open(fil) as f:
    for line in f:
        if not line.startswith('HERE IT IS'):
            print(line, end="")

Enregistrez le script dans un fichier, dites script.py, puis exécutez-le via la commande ci-dessous sur le terminal.

python3 script.py infile
Avinash Raj
la source
vous pourriez y utiliser des expressions rationnelles [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)], mais ce n'est pas beaucoup plus efficace que startswith. Je me demandais comment [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]ne produirait pas la sortie dans une liste.
Avinash Raj
La première fois que je l'ai rencontré, cela m'a semblé étrange. Il génère une commande d'impression (ou toute action que vous souhaitez effectuer avec) pour tous les éléments de la liste définie.
Jacob Vlijm
Undeleting it, just for fun :)
Jacob Vlijm
1

Vous pouvez utiliser Vim en mode Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g recherche globale

  2. d supprimer

  3. x sauver et fermer

Steven Penny
la source