Supprimer des lignes dans un fichier texte qui contiennent une chaîne spécifique

Comment puis-je utiliser sed pour supprimer toutes les lignes d'un fichier texte qui contiennent une chaîne spécifique?

1374
demandé sur codeforester 2011-03-23 22:46:07

14 réponses

Pour supprimer la ligne et imprimer la sortie standard:

sed '/pattern to match/d' ./infile

pour modifier directement le fichier:

sed -i '/pattern to match/d' ./infile

pour modifier directement le fichier (et créer une sauvegarde):

sed -i.bak '/pattern to match/d' ./infile

pour les utilisateurs de Mac OS X et FreeBSD:

sed -i '' '/pattern/d' ./infile
2075
répondu SiegeX 2018-09-07 12:22:11

il existe de nombreuses autres façons de supprimer des lignes avec une chaîne spécifique en plus de sed :

AWK

awk '!/pattern/' file > temp && mv temp file

Ruby (1.9+)

ruby -i.bak -ne 'print if not /test/' file

Perl

perl -ni.bak -e "print unless /pattern/" file

Shell (bash 3.2 et versions ultérieures)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

GNU grep

grep -v "pattern" file > temp && mv temp file

et bien sûr sed (l'impression de l'inverse est plus rapide que la suppression réelle):

sed -n '/pattern/!p' file
543
répondu kurumi 2018-09-15 22:06:06

Vous pouvez utiliser sed pour remplacer les lignes en place dans un fichier. Cependant, il semble être beaucoup plus lent que l'utilisation de grep pour l'inverse dans un deuxième fichier et ensuite déplacer le deuxième fichier sur l'original.

p.ex.

sed -i '/pattern/d' filename      

ou

grep -v "pattern" filename > filename2; mv filename2 filename

la première commande prend 3 fois plus de temps sur ma machine de toute façon.

192
répondu slashdottir 2015-08-19 15:07:10

la manière facile de le faire, avec GNU sed :

sed --in-place '/some string here/d' yourfile
54
répondu Kevin Nguyen 2017-12-11 23:50:54

vous pouvez envisager d'utiliser ex (qui est un éditeur de commandes Unix standard):

ex +g/match/d -cwq file

où:

  • + exécute donné Ex de commande ( man ex ), de même que -c qui s'exécute wq (écrire et quitter)
  • g/match/d - commande Ex pour supprimer les lignes avec match , voir: puissance de g

l'exemple ci-dessus est une méthode conforme à POSIX pour éditer en place un fichier selon ce post sur Unix.SE et spécifications POSIX pour ex .


la différence avec sed est que:

sed est un S tream ED itor, pas un éditeur de fichier. BashFAQ

sauf si vous aimez le code importable, l'E / S au-dessus et d'autres mauvais effets secondaires. Ainsi, fondamentalement, certains paramètres (tels que in-place/ -i ) sont des extensions FreeBSD non standard et peuvent ne pas être disponibles sur d'autres systèmes d'exploitation.

26
répondu kenorb 2018-09-15 22:08:57

je me débattais avec ça sur Mac. En plus, j'avais besoin de le faire en utilisant le remplacement variable.

donc j'ai utilisé:

sed -i '' "/$pattern/d" $file

$file est le fichier où la suppression est nécessaire et $pattern est le motif pour être assorti de la suppression.

j'ai choisi le '' de ce commentaire .

La chose à noter ici est l'utilisation de double guillemets in "/$pattern/d" . Variable ne fonctionne pas lorsque nous utilisons des guillemets simples.

13
répondu Aniket Sinha 2018-09-15 22:15:45

pour obtenir un résultat identique à grep vous pouvez faire ceci:

echo "$(grep -v "pattern" filename)" >filename
12
répondu Jahid 2015-06-13 19:24:59

j'ai fait un petit test avec un fichier qui contient environ 345 000 lignes. La voie avec grep semble être environ 15 fois plus rapide que la méthode sed dans ce cas.

j'ai essayé à la fois avec et sans le paramètre LC_ALL=C, il ne semble pas changer les horaires de manière significative. La chaîne de recherche (CDGA_00004.pdbqt.gz.tar) est quelque part au milieu du fichier.

Voici les commandes et les horaires:

time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt

real    0m0.711s
user    0m0.179s
sys     0m0.530s

time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt

real    0m0.105s
user    0m0.088s
sys     0m0.016s

time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )

real    0m0.046s
user    0m0.014s
sys     0m0.019s
10
répondu Jadzia 2017-03-19 12:45:18

Vous pouvez également utiliser ceci:

 grep -v 'pattern' filename

ici -v imprimera seulement autre que votre modèle (qui signifie correspondance inverse).

7
répondu Bhuvanesh 2018-09-15 22:07:13

echo -e "/thing_to_delete\ndd3:x\n" | vim file_to_edit.txt

2
répondu Shizzmo 2016-09-16 23:51:31
perl -i    -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3

La première commande modifie le fichier(s) place (-i).

La deuxième commande fait la même chose, mais conserve une copie ou sauvegarde du fichier d'origine(s) par l'ajout d' .bk pour les noms de fichier (.bk peut être changé en n'importe quoi).

2
répondu Kjetil S. 2018-01-08 12:07:39
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
0
répondu Andrey Izman 2018-06-29 16:45:24

juste au cas où quelqu'un voudrait le faire pour des Correspondances exactes de cordes, vous pouvez utiliser le drapeau -w dans grep - w pour entier. C'est, par exemple, si vous souhaitez supprimer les lignes qui ont le numéro 11, mais de maintenir les lignes avec le numéro 111:

-bash-4.1$ head file
1
11
111

-bash-4.1$ grep -v "11" file
1

-bash-4.1$ grep -w -v "11" file
1
111

il fonctionne aussi avec le drapeau -f si vous voulez exclure plusieurs motifs exacts à la fois. Si "blacklist" est un fichier avec plusieurs motifs sur chaque ligne que vous voulez supprimer de "file":

grep -w -v -f blacklist file
0
répondu FatihSarigol 2018-09-15 22:18:52