次sed
のコマンドを使用して、次のメールを削除していますhotmail
。同時に複数の項目を確認できますか?list.txt
(1行に1つの項目)から読み込むことをお勧めします。
sed -i '/^[^,]*,[^,]*hotmail/Id' data.txt
.txtでロードできない場合は、次の方法がありますか?hotmail|gmail|yahoo
data.txt
ライン例:
"foxva****omes****","[email protected]","8*** Rd","Ne***ah","Wi***in","54***","*******"
"foxva****omes****","[email protected]","8*** Rd","Ne***ah","Wi***in","54***","*******"
"foxva****omes****","[email protected]","8*** Rd","Ne***ah","Wi***in","54***","*******"
答え1
sed
ファイルをスクリプトとしてフォーマットできる場合、sed
これは自動的に実行できます。以下はGNUで動作しますsed
。 BSDの場合、sed
2回目の呼び出しはうまくいきます...-i '' -e
sed
sed -ne's|[]\*&^.$/[]|\\&|g' \
-e's|..*|/^@&",/d|p' <./list.txt |
sed -ie'h;s/[^,]*[^@]*//' -f- -eg ./data.txt
これで...
-e's|..*|/^@&",/Id|p' ...
...2行目では、GNUは一致するものをすべて削除sed
します。d
list.txt
大文字と小文字は区別されませんが、他のほとんどの構文エラーと同じです。
各行に対して実行されるスクリプトの先頭にある 2 番目のフィールドの 1 番目のフィールドと@
1 番目のフィールドより前のすべての項目と 1 番目のフィールドを削除して一致を絞り込み、一致確認を実行し、行がすべての一致を通過すると、etsはAを保存します。前のスペースのスクリプトの上部にある行のコピーですg
。h
これにより、ゲームごとにこれを行うsed
必要がなくなります。/^[^,]*,[^,]*.../
もしlist.txt
時間がかかっても決して速いプロセスではないでしょう。grep -F
この場合、優先する必要があります(おそらくこの場合)。
sed
両方grep
できるパフォーマンスの向上 - ほとんどの場合確かにしたがって - 使用される文字セットのサイズが小さくなった場合。たとえば、現在UTF-8ロケールにある場合は、次のようにします。
( export LC_ALL=C
sed -ne's|[]\*&^.$/[]|\\&|g' \
-e's|..*|/^@&",/Id|p' |
sed -ie'h;s/[^,]*[^@]*//' -f-\
-eg ./data.txt
) <./list.txt
...正規表現エンジンは、一致のために数万の異なる文字を考慮する必要はなく、128の可能性のみを考慮するので、世界を変えることができます。いかなる方法でも結果に影響を与えてはいけません。各文字はCロケールのバイトであり、すべての文字が適切に考慮されます。
sed -i
これは最良の状況では信頼できるスイッチではないため、可能であれば避けるべきです。
これを行うには、次を使用します。grep
そして sed -i
:
( export LC_ALL=C
cut -d\" -f4 | cut -d@ -f2 |
grep -Fixnf ./list.txt |
sed -e's|:*\([0-9]*\).*|:\1|p'\
-e's||\1!{p;n;b\1|p' \
-e's||};n|' |
sed -nif- -e:n -e'p;n;bn' \
./data.txt
) <./data.txt
sed
これが私が想像できる最速の方法です-i
。分析方法は次のとおりです。
cut | cut
- 最初の2つは入力ラインを次のように
cut
減らします。./data.txt
"foxva****omes****","[email protected]","8*** Rd","Ne***ah","Wi***in","54***","*******"
hotmail.com
- 最初の2つは入力ラインを次のように
grep
grep
その後、この入力をパターンファイルの各行-f
と比較できます。list.txt
-i
大文字と小文字を区別しない-F
固定文字列を使用して行全体を照合し、出力の各行の先頭に行番号を-x
報告します。-n
sed -e
sed
出力を行番号で削除し、以下のようにgrep
別のスクリプトを作成します。sed
(grep
ライン10と20が一致すると仮定):
:10 10!{p;n;b10 };n :20 20!{p;n;b20 };n
sed -inf-
最後はstdinをスクリプトとして
sed
読み、一度だけ実行します。通常、スクリプトのように、各入力行に対してスクリプトを逆追跡して実行するのではなく、代わりに-
最初で唯一の作業時にスクリプトを実行します。sed
入力 - それだけ対応するテストは、各入力ラインに対して一度だけ試みるべきです。前の例では、行1から9は
sed
次のことを行います。- 現在の行が最初の行ではない場合は、現在の行を
!
印刷10
し{
てそれを追加の入力行で上書きし、名前付きラベルに逆追跡します。p
n
b
:
10
- 現在の行が最初の行ではない場合は、現在の行を
最後の行が印刷
sed
されますp
。次に、現在の行をextで上書きし、n
すべての入力が使用されるまでラベルをb
貼り付けます。:n
次の場合は機能しません。./data.txt
とても大きいです。sed
スクリプトが確実に処理できるよりもはるかに大きい入力ファイルを処理しようとすると、スクリプトが輻輳するためです。この問題に対する解決策は、入力をチャンクに取り込むことです。これできる正しい種類のリーダーを使用すると、パイプラインでもこれを確実に実行できます。dd
正しい種類の読者です。
次のテストファイルを作成しました。
sh -c ' _1=\"foxva****omes****\",\"scott@
_2='\''","8*** Rd","Ne***ah","Wi***in","54***","*******"'\''
n=0
for m do printf "$_1%s$_2\n$_1$((n+=1))not_free.com$_2\n" "$m"
done
' $(cat ~/Downloads/list.txt) >/tmp/data.txt
...どこlist.txt
持っているここあなたの言葉によるとその他の問題。それは次のように動作します...他のすべての行について...
"foxva****omes****","[email protected]","8*** Rd","Ne***ah","Wi***in","54***","*******"
"foxva****omes****","scott@1not_free.com","8*** Rd","Ne***ah","Wi***in","54***","*******"
"foxva****omes****","[email protected]","8*** Rd","Ne***ah","Wi***in","54***","*******"
"foxva****omes****","scott@2not_free.com","8*** Rd","Ne***ah","Wi***in","54***","*******"
それから80mbsを少し増やしました。
while [ "$(($(wc -c <data.txt)/1024/1024))" -lt 80 ]
do cat <<IN >./data.txt
$( cat ./data.txt ./data.txt)
IN
done
ls -hl ./data.txt
wc -l <./data.txt
-rw-r--r-- 1 mikeserv mikeserv 81M Jul 19 22:22 ./data.txt
925952
...それから私は...
( trap rm\ data.tmp 0; export LC_ALL=C
<./data.txt dd bs=64k cbs=512 conv=block |
while dd bs=64k cbs=512 conv=unblock \
count=24 of=./data.tmp
[ -s ./data.tmp ]
do
<./data.tmp cut -d\" -f4 | cut -d@ -f2 |
grep -Fixnf ./list.txt |
sed -e's|:*\([0-9]*\).*|:\1|p' \
-e's||\1!{p;n;b\1|p' \
-e's||};n|' |
sed -nf- -e:n -e'p;n;bn' ./data.tmp
done 2>/dev/null
)| wc -l
1293+1 records in
7234+0 records out
474087424 bytes (474 MB) copied, 21.8488 s, 21.7 MB/s
462976
プロセス全体に22秒かかり、出力行数が少なくとも正確であることがわかります。 462976は925952の半分で、入力は半分にする必要があります。
この手法は、dd
読み書きがバイト単位で計算できるため有効です。実行していることがわかっている場合は、パイプを介して読み書きできます。入力を中断することもできます。行ごとにconv
最大行長サイズで安定して計算できる場合、block
精度は同じです。(これは512または{_POSIX_LINE_MAX}
)。
想像力豊かな読者なら、あちこちでいくつかの修正だけで同じ技術があらゆるタイプのストリーミング(さらにはライブログタイプにも適用可能)に適用できると正確に推測できます。(つまり、これを安全に実行するには、最初のdd
引数bs=
到着obs=
)。ただし、それぞれの場合、最大入力行サイズに対していくつかの保証が必要であり、行が合法的に<space>文字で終わることができる場合は、プロセスの前に追加のフィルタリングメカニズムを挿入して末尾の<spaces>がdd
剥奪されるのを防ぐ必要があります。dd conv=unblock
cbs
(これは、各サイズconv
のバージョンブロックのすべての末尾のスペースを削除し、改行を追加する\n
方法で機能します。)。tr
私は(un|)expand
そのようなフィルタの可能な候補を考えました。
これは最速の方法ではありません。これを行うには見つける必要があります-m
エルグsort
仕事は期待していましたが、非常に高速でデータと連携します。しかし、それはsed -i
状況を少し台無しにします。しかし、どちらの方向に行っても、それは本当だと思います。
答え2
いくつかの異なる方法でこの問題を解決できます。まず、sed
単一の実行で複数の式がサポートされます。
sed -i -e '/^[^,]*,[^,]*hotmail/Id' -e '/^[^,]*,[^,]*gmail/Id' -e '/^[^,]*,[^,]*yahoo/Id' data.txt
単一の式でこれを行うこともできます。
sed -i -e '/^[^,]*,[^,]*\(hotmail\|gmail\|yahoo\)/Id' data.txt
、、、、(
およびすべてエスケープ)
する|
必要があります。