web-dev-qa-db-fra.com

Comment supprimer toutes les occurrences d'une liste de mots à partir d'un fichier texte?

J'ai un fichier contenant une liste de mots. Je veux supprimer toutes les occurrences de tous les mots de ce fichier à partir d'un gros fichier texte.

Exemple:

Fichier 1

queen
king

Exemple de fichier texte

Both the king and queen are monarchs. Will the queen live? Queen, it is!

C'est ce que j'ai essayé:

sed -i 's/queen/ /g' page.txt
sed -i 's/Queen/ /g' page.txt

Sortir

Both the and are monarchs. Will the live? , it is!

La liste des mots que j'ai est grosse (plus de 50000 mots). Comment puis-je faire cela sans avoir à spécifier le motif de la ligne de commande?

8
user199046

Pour votre cas d'utilisation réelle, je vous recommande réponse de Terdon à l'aide de Perl .

Cependant, la version simple, sans manipuler des mots qui sont des sous-chaînes d'autres mots (par exemple, retirer le "roi" de "randonnée"), est de tiliser un Sed pour générer la commande Exécutez par un différent Sed instance sur votre fichier actuel.

Dans ce cas, avec wordfile contenant "roi" et "reine" et textfile contenant votre texte:

sed -e "$(sed 's:.*:s/&//ig:' wordfile)" textfile

Notez que le drapeau "i nore" Le drapeau "est un GNU extension, non standard.

5
Wildcard

La manière simple mais inefficace est de traiter le fichier plusieurs fois, une fois pour chaque mot d'entrée:

$ while read w; do sed -i "s/$w//ig" file2 ; done < file1
$ cat file2
Both the  and  are monarchs. Will the  live? , it is!

Cela peut être très lent pour les gros fichiers (et correspond également à des substrings). Vous pouvez le faire en une seule passe avec Perl:

Perl -lpe 'BEGIN{open(A,"file1"); chomp(@k = <A>)} 
                 for $w (@k){s/\b\Q$w\E\b//ig}' file2 

Les \b Assurez-vous que nous ne correspondons que sur les limites de mots, \Q\E s'assurer $w est pris littéralement. Cela empêchera le script d'assortir hiking mais cela correspondra toujours à high-king. Pour éviter cela, vous devez énumérer explicitement les personnages qui définissent un mot:

Perl -Mopen=locale -Mutf8 -lpe '
  BEGIN{open(A,"file1"); chomp(@k = <A>)} 
  for $w (@k){s/(^|[ ,.—_;-])\Q$w\E([ ,.—_;-]|$)/$1$2/ig}' file2 

Cette Le caractère non-ASCII ci-dessus doit être entré dans l'encodage UTF-8, car nous disons Perl Le code est écrit dans UTF-8 avec -Mutf8. Nous utilisons -Mopen=locale Pour que le contenu des fichiers et de stdout soit décodé/codé dans le jeu de caractères de la locale.

3
terdon

enregistrez ce script sur le fichier d: ( Télécharger GitHub Gist )

#!/bin/bash

LIST=${1:?"LIST Word"}
FILE=${2:?"FILE name not set"}

L=$( sed -e ':a;N;$!ba;s_\n_\x00_g' ${LIST}|sed -e 's_\x00_ \\|_g' -e's_\(\\|\)*$__g')
P='s_\('$L'\)__ig'
O="sed -e '$P'  ${FILE}"

eval "${O}"

puis exécutez-le:

bash ./d LIST FILE 

si vous souhaitez enregistrer un fichier, vous pouvez exécuter cette commande:

bash ./d LIST FILE  | tee NewFILE

OR

bash ./d LIST FILE > NewFile

je lis la liste de liste et le modifier à Regex Foramt, par exemple, je modifie votre queen et king et test à ce format:

queen\|king\|test

ensuite, Créez une commande sed avec ce paramètre:

sed -e 's_\(queen\|king\|test\) *__ig' FILE

avec ce script Bash, nous lisons une fois LISTWORD et une fois FILE pour remplacer

0
بارپابابا