web-dev-qa-db-ja.com

特定の文字列を含むテキストファイル内の行を削除する

特定の文字列を含むテキストファイル内のすべての行を削除するのにsedをどのように使用しますか

1461

行を削除して出力を標準出力に出力するには、次のようにします。

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

ファイルを直接変更するには

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

ファイルを直接変更する(そしてバックアップを作成する)には:

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

Mac OS XおよびFreeBSDユーザーの場合:

sed -i '' '/pattern/d' ./infile
2251
SiegeX

sed以外にも、特定の文字列を含む行を削除する方法は他にもたくさんあります。

AWK

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

ルビー(1.9+)

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

Perl

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

シェル(bash 3.2以降)

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

そしてもちろんsed(逆の出力は実際の削除より速いです):

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

ファイル内の所定の位置にある行を置き換えるには、sedを使用します。しかし、grepを使って2番目のファイルに変換してから2番目のファイルを元のファイルの上に移動するよりもはるかに遅いようです。

例えば.

sed -i '/pattern/d' filename      

または

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

とにかく最初のコマンドは私のマシンで3倍長くかかります。

204
slashdottir

簡単な方法は、GNU sed

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

あなたは ex (これは標準のUnixコマンドベースのエディタです)を使うことを考えるかもしれません:

ex +g/match/d -cwq file

ここで、

  • wqを実行する+と同じように、man exは与えられたExコマンド(-c)を実行します(writeとquit)。
  • g/match/d - 与えられたmatchを持つ行を削除するExコマンド。参照: gの累乗

上記の例は、この Unix.SEに投稿 および ex のように、ファイルをインプレース編集するためのPOSIX準拠の方法です。


sedとの違いは、

sed _ s _ tream _ ed _ itorであり、ファイルエディタではありません。BashFAQ

移植できないコード、I/Oオーバーヘッド、その他の悪い副作用を楽しんでいない限り。そのため、基本的には(in-place/-iのような)いくつかのパラメータは標準ではないFreeBSDの拡張機能であり、他のオペレーティングシステムでは利用できないかもしれません。

27
kenorb

私はMac上でこれに苦労していました。さらに、変数置換を使用してそれを実行する必要がありました。

だから私は使用しました:

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

$fileは削除が必要なファイルで、$patternは削除のために照合されるパターンです。

私はこの コメント から''を選びました。

ここで注意すべきことは"/$pattern/d" 二重引用符 を使用することです。一重引用符を使用すると、変数は機能しません。

13
Aniket Sinha

grepでインプレース風の結果を得るためには、これを実行できます。

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

私は約34万5000行を含むファイルで小さなベンチマークを作成しました。この場合のgrepメソッドはsedメソッドよりも約15倍速いようです。

LC_ALL = Cを設定してもしなくても試してみましたが、タイミングが大きく変わることはありません。検索文字列(CDGA_00004.pdbqt.gz.tar)はファイルの途中のどこかにあります。

コマンドとタイミングは次のとおりです。

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

これを使うこともできます。

 grep -v 'pattern' filename

ここで-vはあなたのパターン以外のものだけを印刷するでしょう(それは逆マッチを意味します)。

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

最初のコマンドは、ファイルをその場で編集します(-i)。

2番目のコマンドも同じことを行いますが、ファイル名に.bkを追加することで元のファイルのコピーまたはバックアップを保持します(.bkは任意の名前に変更できます)。

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

万が一、文字列が完全に一致するようにしたい場合は、grep-wの-wフラグを使用してください。たとえば、番号11の行を削除したいが、番号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

同時に複数の正確なパターンを除外したい場合は、-fフラグと一緒に機能します。 "blacklist"が "file"から削除したい各行に複数のパターンを持つファイルであるならば:

grep -w -v -f blacklist file
0
FatihSarigol