web-dev-qa-db-fra.com

Supprimer les lignes d'un fichier texte contenant une chaîne spécifique

Comment utiliser sed pour supprimer toutes les lignes d'un fichier texte contenant une chaîne spécifique?

1461
A Clockwork Orange

Pour supprimer la ligne et imprimer le résultat en 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
2251
SiegeX

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

Rubis (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 ultérieur)

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 (imprimer l'inverse est plus rapide que la suppression réelle):

sed -n '/pattern/!p' file
568
kurumi

Vous pouvez utiliser sed pour remplacer les lignes en place dans un fichier. Cependant, cela semble être beaucoup plus lent que d'utiliser grep pour l'inverse dans un second fichier, puis de déplacer le second fichier sur l'original.

par exemple.

sed -i '/pattern/d' filename      

ou

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

La première commande prend quand même 3 fois plus de temps sur ma machine.

204
slashdottir

Le moyen facile de le faire, avec GNU sed:

sed --in-place '/some string here/d' yourfile
58
Kevin Nguyen

Vous pouvez envisager d'utiliser ex (qui est un éditeur standard basé sur des commandes Unix):

ex +g/match/d -cwq file

où:

  • + exécute la commande Ex donnée (man ex), identique à -c qui exécute wq (écrire et quitter)
  • g/match/d - Commande Ex pour supprimer les lignes avec match donné, voir: Puissance de g

L'exemple ci-dessus est une méthode compatible POSIX pour la modification sur place d'un fichier conformément à ce post sous 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 appréciez du code non transférable, des frais généraux d’E/S et d’autres mauvais effets secondaires. Ainsi, 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.

27
kenorb

Je me débattais avec ça sur Mac. De plus, je devais le faire en utilisant le remplacement variable.

Alors j'ai utilisé:

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

$file est le fichier où la suppression est nécessaire et $pattern est le modèle à rechercher pour la suppression.

J'ai choisi le '' de ce commentaire .

La chose à noter ici est l’utilisation de doubles guillemets dans "/$pattern/d". La variable ne fonctionnera pas lorsque nous utilisons des guillemets simples.

13
Aniket Sinha

Pour obtenir un résultat similaire à grep, vous pouvez procéder comme suit:

echo "$(grep -v "pattern" filename)" >filename
12
Jahid

J'ai créé un petit repère avec un fichier contenant environ 345 000 lignes. La méthode avec grep semble être environ 15 fois plus rapide que la méthode sed dans ce cas.

J'ai essayé les deux avec et sans le paramètre LC_ALL = C, il ne semble pas changer les timings de manière significative. La chaîne de recherche (CDGA_00004.pdbqt.gz.tar) se situe quelque part au milieu du fichier.

Voici les commandes et les timings:

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
11
Jadzia

Vous pouvez aussi utiliser ceci:

 grep -v 'pattern' filename

Ici, -v n'imprimera que d'autres motifs que votre motif (cela signifie que la correspondance est inversée).

9
Bhuvanesh
8
Oleg Mazko

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

2
Shizzmo
Perl -i    -nle'/regexp/||print' file1 file2 file3
Perl -i.bk -nle'/regexp/||print' file1 file2 file3

La première commande édite le ou les fichiers in-situ (-i).

La deuxième commande fait la même chose, mais conserve une copie ou une sauvegarde du ou des fichiers d'origine en ajoutant .bk aux noms de fichiers (le nom de fichier .bk peut être changé).

2
Kjetil S.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
0
Andrey Izman

Juste au cas où quelqu'un voudrait le faire pour des correspondances exactes de chaînes, vous pouvez utiliser l'indicateur -w dans grep -w pour le nombre entier. C’est-à-dire, par exemple, si vous souhaitez supprimer les lignes portant le numéro 11, tout en conservant les lignes portant 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

Cela fonctionne également avec l'indicateur -f si vous souhaitez exclure plusieurs modèles exacts à la fois. Si "liste noire" est un fichier avec plusieurs motifs sur chaque ligne que vous souhaitez supprimer de "fichier":

grep -w -v -f blacklist file
0
FatihSarigol