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?
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.
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.
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