सबसे तेज़ संभव grep


80

मैं जानना चाहूंगा कि क्या कोई टिप है grepजितना जल्दी संभव हो सके। मेरे पास त्वरित संभव तरीके से खोज करने के लिए पाठ फ़ाइलों का एक बड़ा आधार है। मैंने उन सभी लोअरकेस को बनाया है, ताकि मुझे -iविकल्प से छुटकारा मिल सके । इससे खोज काफी तेज होती है।

इसके अलावा, मुझे पता चला है कि -Fऔर -Pमोड डिफ़ॉल्ट एक से तेज हैं। मैं पूर्व का उपयोग करता हूं जब खोज स्ट्रिंग एक नियमित अभिव्यक्ति (सिर्फ सादा पाठ) नहीं है, तो उत्तरार्द्ध यदि रेगेक्स शामिल है।

क्या किसी को भी तेज करने का कोई अनुभव है grep? हो सकता है कि इसे किसी विशेष ध्वज (मैं लिनक्स सेंटो पर) के साथ खरोंच से संकलित करूं, फाइलों को एक निश्चित फैशन में व्यवस्थित करें या हो सकता है कि खोज किसी तरह समानांतर हो?


1
क्या यह हमेशा फ़ाइलों का एक ही सेट है? यदि आप अपने आप को फ़ाइलों के समान (बड़े) सेट को खोजते हुए पाते हैं grep, तो शायद उन्हें ठीक से अनुक्रमित करने के लिए एक समाधान की तलाश करने का समय है ("सर्वश्रेष्ठ" समाधान इस बात पर निर्भर करेगा कि ये किस प्रकार की फाइलें हैं)।
FatalError

हाँ, यह फ़ाइलों का एक ही सेट है। क्या आपको लगता है कि ल्यूसिन की तरह एक पूर्ण समाधान प्रदर्शन में सुधार करेगा? आम तौर पर लगभग 250 मिलियन शब्दों की कुल शब्द गणना के लिए 2500 फाइलों (प्रत्येक साहित्यिक पुस्तक) के माध्यम से एक खोज करने में लगभग 30/40 सेकंड लगते हैं।
पिस्ताचियो

1
"...or maybe make the search parallel in some way?"मैं इस बारे में सुनने के लिए वास्तव में उत्साहित हूँ। grepपूरी तरह से समानांतर में संचालित करने में सक्षम होना चाहिए, लेकिन मुझे संदेह है कि खोज अभी भी I / O बाध्य हो सकती है।
कॉनरैड.डीन

2
क्या आपने प्रयोग करने की कोशिश की है ack-grep?
मध्याह्न सर्वव्यापी

जवाबों:


104

जीएनयू समानांतर के साथ प्रयास करें , जिसमें इसका उपयोग कैसे करें का एक उदाहरणgrep शामिल है :

grep -rनिर्देशिकाओं के माध्यम से संक्षिप्त रूप से। मल्टीकोर सीपीयू पर GNU parallelअक्सर इसे गति दे सकता है।

find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {}

यह प्रति कोर 1.5 नौकरी चलाएगा, और 1000 तर्क देगा grep

बड़ी फ़ाइलों के लिए, यह इसे तर्कों --pipeऔर --blockतर्कों के साथ कई खंडों में विभाजित कर सकता है:

 parallel --pipe --block 2M grep foo < bigfile

आप इसे SSH के माध्यम से कई अलग-अलग मशीनों पर भी चला सकते हैं (पासवर्ड से बचने के लिए आवश्यक ssh- एजेंट):

parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile

5
--color=alwaysgrep रंग को संरक्षित करने के लिए उपयोग करें (यह सच है जब भी आप किसी पाइप में grep का उपयोग कर रहे हों)
जिम

2
अगर findहै -print0इसका इस्तेमाल के लिए बेहतर होगा विधेय (सबसे अधिक है) find . -type f -print0 | parallel -0 -k …man(1) parallelवास्तव में मेरा उदाहरण यह कहता है। इसके अलावा, मुझे संदेह है globstarकि अगर आप किसी विशेष फ़ाइल पैटर्न के बाद भी इसे तेज कर सकते हैं:shopt -s globstar; parallel -k -j150% -n 1000 -m fgrep -H -n STRING ::: **/*.c
kojiro

3
catअगर आप sudoएक्सेस करना चाहते हैं तो @illiamPursell इसका उपयोगी उपयोग हैbigfile
Jayen

2
आप प्रति कोर 1.5 नौकरियां क्यों सेट करते हैं? प्रति कोर 1 काम क्यों नहीं?
जॉनगॉल्ट

2
@ जॉन्गल्ट अक्सर डिस्क I / O प्रक्रियाओं में से एक को रोक देगा। कोर की तुलना में कुछ अधिक शुरू करने से, सभी कोर के लिए अभी भी सामान करना होगा - भले ही कुछ नौकरियां डेटा की प्रतीक्षा कर रही हों। अपने सिस्टम पर सबसे अच्छा काम करने के लिए 150% समायोजित करें।
ओले तांगे

70

यदि आप बहुत बड़ी फ़ाइलों को खोज रहे हैं, तो अपने स्थान को सेट करना वास्तव में मदद कर सकता है।

GNU grep UTF-8 की तुलना में C लोकेल में बहुत तेजी से आगे बढ़ता है।

export LC_ALL=C

1
प्रभावशाली, ऐसा लगता है कि यह एकल पंक्ति 2X गति देती है।
फेडिर RYKHTIK

क्या कोई समझा सकता है कि ऐसा क्यों है?
रॉबर्ट ई मैले

5
"सरल बाइट तुलना बनाम कई बाइट चरित्र तुलना" <मेरे मालिक कहते हैं ... दाईं ओर दाईं ओर
रॉबर्ट ई Mealey

7
तो यह बिल्कुल सुरक्षित नहीं है, खासकर यदि आप पैटर्न मिलान (केवल स्ट्रिंग मिलान के विपरीत) या यदि आपकी फ़ाइल की सामग्री एएससीआई नहीं है। अभी भी कुछ मामलों में करने लायक है लेकिन सावधानी बरतें।
रॉबर्ट ई मेले

@RobertEMealey क्या उसने "सरल" के बजाय "सिंगल" कहा था?
एलिजा लिन

12

रिपग्रेप का दावा है कि अब सबसे तेज होगा।

https://github.com/BurntSushi/ripgrep

इसमें डिफ़ॉल्ट रूप से समानता भी शामिल है

 -j, --threads ARG
              The number of threads to use.  Defaults to the number of logical CPUs (capped at 6).  [default: 0]

README से

इसे रस्ट के रेगेक्स इंजन के ऊपर बनाया गया है। रस्ट का रेगेक्स इंजन खोज को बहुत तेज़ बनाने के लिए परिमित ऑटोमेटा, SIMD और आक्रामक शाब्दिक अनुकूलन का उपयोग करता है।


यह अविश्वसनीय रूप से तेज है!
हराया


4

कड़ाई से एक कोड में सुधार नहीं है, लेकिन 2+ मिलियन फाइलों पर grep चलाने के बाद मुझे कुछ मदद मिली।

मैंने ऑपरेशन को सस्ते SSD ड्राइव (120GB) पर स्थानांतरित किया। लगभग 100 डॉलर में, यह एक किफायती विकल्प है यदि आप नियमित रूप से बहुत सारी फ़ाइलों को क्रंच कर रहे हैं।


3

आप परवाह नहीं है तो फाइलों के बारे में जो स्ट्रिंग है, तो आप को अलग करने के लिए चाहते हो सकता पढ़ने और grepping दो नौकरियां में है, क्योंकि यह अंडे देने के लिए महंगा हो सकता है grepप्रत्येक छोटे फ़ाइल के लिए एक बार - कई बार।

  1. यदि आपके पास एक बहुत बड़ी फ़ाइल है:

    parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>

  2. कई छोटी संपीड़ित फ़ाइलें (इनोड द्वारा क्रमबद्ध)

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>

मैं आमतौर पर अधिकतम थ्रूपुट के लिए lz4 के साथ अपनी फ़ाइलों को संपीड़ित करता हूं।

  1. यदि आप मैच के साथ सिर्फ नाम चाहते हैं:

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}


2

सैंड्रो की प्रतिक्रिया के आधार पर मैंने यहां दिए गए संदर्भ को देखा और बीएसडी जीआरपी बनाम जीएनयू जीआरईपी के साथ खेला। मेरे त्वरित बेंचमार्क परिणामों ने दिखाया: जीएनयू जीआरपी रास्ता है, तेजी से।

तो मूल प्रश्न "सबसे तेज़ संभव grep" के लिए मेरी सिफारिश: सुनिश्चित करें कि आप BSD grep (उदाहरण के लिए MacOS पर डिफ़ॉल्ट) के बजाय GNU grep का उपयोग कर रहे हैं।


मैं अपने 13 "मैकबुक प्रो पर BSD Grep को तेजी से दिखा रहा हूं, 250 एमबी की खोज करते हुए 8GB, 6-कोर
लाइनोड की तुलना में। 6q

2

मैं व्यक्तिगत रूप से grep के बजाय ag (सिल्वर खोजकर्ता) का उपयोग करता हूं और यह तेज़ है, साथ ही आप इसे समानांतर और पाइप ब्लॉक के साथ जोड़ सकते हैं।

https://github.com/ggreer/the_silver_searcher

अपडेट: मैं अब https://github.com/BurntSushi/ripgrep का उपयोग करता हूं, जो आपके उपयोग के मामले के आधार पर एजी से तेज है।


मुझे इसमें एक बग नजर आया। कभी-कभी यह पेड़ में गहराई तक नहीं जाता है और मेरे पास ऐसे मामले हैं जहां जीआरपी परिणाम दिखाता है लेकिन एजी नहीं करता है। मैं गति के लिए सटीकता पर समझौता नहीं कर सकता।
username_4567

1
आपको उनके गीथूब खाते पर एक मुद्दा खोलना चाहिए और इसे रिपोर्ट करना चाहिए (मैं ऐसा करूंगा लेकिन मैं इसे दोहरा नहीं सकता), क्योंकि अब तक मुझे कोई अशुद्धि नहीं मिली थी। यकीन है कि वे इसे सुलझा लेंगे और हां आप सही हैं मैं पूरी तरह से सहमत हूं: पहले सटीकता।
जिंक्समैग

1

किसी एक बड़ी फ़ाइल में खोज (विशेष रूप से पैटर्न को बदलने के लिए) के लिए grep का उपयोग करने के लिए मैंने एक चीज़ और तेज़ कर दी है, वह है समांतर ध्वज के साथ विभाजित + grep + xargs का उपयोग करना। उदाहरण के लिए:

आईडी की एक फ़ाइल होने से आप एक बड़ी फ़ाइल में खोज करना चाहते हैं जिसे my_ids.txt कहा जाता है। bigfile bigfile.txt का नाम

फ़ाइल को भागों में विभाजित करने के लिए स्प्लिट का उपयोग करें:

# Use split to split the file into x number of files, consider your big file
# size and try to stay under 26 split files to keep the filenames 
# easy from split (xa[a-z]), in my example I have 10 million rows in bigfile
split -l 1000000 bigfile.txt
# Produces output files named xa[a-t]

# Now use split files + xargs to iterate and launch parallel greps with output
for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done
# Here you can tune your parallel greps with -P, in my case I am being greedy
# Also be aware that there's no point in allocating more greps than x files

मेरे मामले में यह कटौती 1 घंटे 20 मिनट की नौकरी में 17 घंटे की नौकरी क्या होगी। मुझे यकीन है कि दक्षता पर यहाँ किसी प्रकार का बेल वक्र है और स्पष्ट रूप से उपलब्ध कोर पर जाने से आपको कोई फायदा नहीं होगा, लेकिन यह ऊपर बताई गई मेरी आवश्यकताओं के लिए किसी भी उपरोक्त टिप्पणी की तुलना में बहुत बेहतर समाधान था। यह ज्यादातर (linux) देशी उपकरणों का उपयोग करने में समानांतर स्क्रिप्ट पर एक अतिरिक्त लाभ है।



0

MCE 1.508 में एक दोहरी चंक-स्तर {फ़ाइल, सूची} कई सी बायनेरी का समर्थन करने वाली आवरण स्क्रिप्ट शामिल है; agrep, grep, egrep, fgrep, और tre-agrep।

https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep

https://metacpan.org/release/MCE

जब चाहा -i को तेज दौड़ने के लिए लोअरकेस में बदलने की जरूरत नहीं है। बस पास - lang = C से mce_grep।

आउटपुट ऑर्डर संरक्षित है। -N और -b आउटपुट भी सही है। दुर्भाग्य से, यह इस पृष्ठ पर वर्णित जीएनयू समानांतर के लिए मामला नहीं है। मैं वास्तव में यहां काम करने के लिए जीएनयू समानांतर के लिए उम्मीद कर रहा था। इसके अलावा, mce_grep करता नहीं उप खोल (श -c / path / to / ग्रेप) जब द्विआधारी बुला।

एक अन्य वैकल्पिक MCE :: Grep मॉड्यूल है जो MCE के साथ शामिल है।


आपको उक्त टूल के लेखक होने के नाते एक डिस्क्लेमर प्रदान करना होगा।
फ्रैक्टलस्पेस

0

मूल विषय से थोड़ा सा विचलन: googlecodesearch परियोजना से अनुक्रमित खोज कमांड लाइन उपयोगिताओं की तुलना में तेजी से रास्ता है: https://github.com/google/codesearch :

एक बार जब आप इसे संकलित करते हैं ( गोलंग पैकेज की आवश्यकता होती है), आप एक फ़ोल्डर को इसके साथ अनुक्रमित कर सकते हैं:

# index current folder
cindex .

के तहत सूचकांक बनाया जाएगा ~/.csearchindex

अब आप खोज सकते हैं:

# search folders previously indexed with cindex
csearch eggs

मैं अभी भी रंग मिलान पाने के लिए grep के माध्यम से परिणामों को पाइप कर रहा हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.