web-dev-qa-db-ja.com

テキストファイルから単語リストのすべての出現を削除する方法

単語のリストを含むファイルがあります。大きなテキストファイルからこのファイル内のすべての単語の出現をすべて削除したい。

例:

ファイル1

queen
king

テキストファイルのサンプル

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

これは私が試したものです:

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

出力

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

私が持っている単語のリストは大きい(50000語以上)。コマンドラインでパターンを指定せずにこれを行うにはどうすればよいですか?

8
user199046

あなたの実際のユースケースでは、私は Perlを使用したterdonの回答 をお勧めします。

ただし、他の単語の部分文字列である単語を処理しない(たとえば、「king」を「hiking」から削除する)単純なバージョンは、次のようになります se one Sed command to generate the command実際のファイルに対して別のSedインスタンス で実行します。

この場合、wordfileには「king」と「queen」が含まれ、textfileにはテキストが含まれます。

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

"ignore case"フラグはGNU拡張であり、標準ではないことに注意してください。

5
Wildcard

単純ですが非効率的な方法は、ファイルを複数回処理することです。1回の入力Wordごとに1回です。

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

ただし、大きなファイルの場合は非常に遅くなる可能性があります(サブストリングにも一致します)。あなたはPerlを使って1回のパスでそれを行うことができます:

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

\bは、単語の境界でのみ一致することを確認します。\Q\Eは、$wが文字どおりに解釈されるようにします。これにより、スクリプトはhikingに一致しなくなりますが、high-kingには一致します。これを回避するには、Wordを定義する文字を明示的にリストする必要があります。

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

上記の非ASCII文字は、UTF-8エンコーディングで入力する必要があります。これは、Perl-Mutf8を使用してコードをUTF-8で記述しているためです。ロケールの文字セットでデコード/エンコードされるファイルとstdoutのコンテンツに-Mopen=localeを使用しています。

3
terdon

このスクリプトをファイルdに保存します:( 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}"

それを実行します:

bash ./d LIST FILE 

ファイルを保存したい場合は、次のコマンドを実行できます。

bash ./d LIST FILE  | tee NewFILE

OR

bash ./d LIST FILE > NewFile

私はLIST Wordを読んでそれを正規表現形式に変更します。たとえば、queenkingtestを次の形式に変更します。

queen\|king\|test

次に、このパラメーターを使用してsedコマンドを作成します。

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

このbashスクリプトを使用して、LISTWORDを1回、置換のためにFILEを1回読み取ります

0