grep -n | sort | sed | cut
( export LC_ALL=C
grep -n '' | sort -t: -nmk1,1 ./L - |
sed /:/d\;n | cut -sd: -f2-
) <./F
किसी भी आकार के इनपुट के साथ बहुत जल्दी काम करना चाहिए (कुछ समयबद्ध परीक्षण नीचे शामिल हैं) । कुछ नोट्स कैसे:
export LC_ALL=C
- क्योंकि निम्न ऑपरेशन की बात यह है कि
./F
इसकी ./L
लाइनिनो की फाइल के साथ स्टैक्ड अप इनलाइन की पूरी फाइल प्राप्त करना है , केवल उन पात्रों के बारे में जिन्हें हमें चिंता करने की आवश्यकता होगी ASCII [0-9]
अंक और :
कोलन।
- इस कारण से यह अधिक सरल है कि यूटीएफ -8 अन्यथा शामिल होने की तुलना में 128 कब्जे के सेट में उन 11 पात्रों को खोजने के बारे में चिंता करना।
grep -n ''
- यह स्ट्रिंग
LINENO:
को स्टाइन में हर पंक्ति के सिर में सम्मिलित करता है - या <./F
।
sort -t: -nmk1,1 ./L -
sort
अपनी इनपुट फाइलों को क्रमबद्ध करने के लिए उपेक्षा करता है, और इसके बजाय (सही ढंग से) मान लिया जाता है कि वे हैं और क्रमबद्ध क्रम -m
में उन्हें मिटा देता है -numerically
, वैसे भी मूल रूप से किसी भी संभावित -k1,1
सेंट -t:
बृहदान्त्र चरित्र से परे कुछ भी अनदेखा कर रहा है।
- हालांकि ऐसा करने के लिए कुछ अस्थायी स्थान की आवश्यकता हो सकती है (यह निर्भर करता है कि कुछ क्रम कितने अलग हो सकते हैं) , इसे उचित प्रकार की तुलना में बहुत अधिक आवश्यकता नहीं होगी, और यह बहुत तेज़ होगा क्योंकि इसमें शून्य बैकट्रैकिंग शामिल है।
sort
एक एकल स्ट्रीम का उत्पादन करेगा जहां किसी भी लिनेनो में ./L
तुरंत संबंधित लाइनों को पूर्ववर्ती किया जाएगा ./F
। ./L
की लाइनें हमेशा पहले आती हैं क्योंकि वे छोटी होती हैं।
sed /:/d\;n
- यदि वर्तमान लाइन एक
/:/
बृहदान्त्र से मेल खाती है तो d
इसे आउटपुट से हटा दिया जाता है। एल्स, वर्तमान और n
एक्सट्रीम लाइन को ऑटो-प्रिंट करें ।
- और इसलिए
sed
आलूबुखारा sort
करने के उत्पादन केवल अनुक्रमिक लाइन जोड़े जो एक बृहदान्त्र और निम्न पंक्ति मेल नहीं - से केवल एक लाइन के लिए या, ./L
और फिर अगले।
cut -sd: -f2-
cut
-s
इसके उन इनपुट लाइनों के आउटपुट से ऊपर की ओर जो कि इसके -d:
एलिमिटर स्ट्रिंग्स में से कम से कम एक नहीं होती है - और इसलिए इन ./L
लाइनों को पूरी तरह से काट दिया जाता है।
- उन पंक्तियों के लिए जो करते हैं, उनका पहला
:
बृहदान्त्र-सीमांकित -f
आईलिड cut
दूर होता है - और इसलिए सभी grep
लिनेनो के सम्मिलित होते हैं।
छोटे इनपुट परीक्षण
seq 5 | sed -ne'2,3!w /tmp/L
s/.*/a-z &\& 0-9/p' >/tmp/F
... नमूना इनपुट की 5 लाइनें उत्पन्न करता है। फिर...
( export LC_ALL=C; </tmp/F \
grep -n '' | sort -t: -nmk1,1 ./L - |
sed /:/d\;n | cut -sd: -f2-
)| head - /tmp[FL]
... प्रिंट ...
==> standard input <==
a-z 1& 0-9
a-z 4& 0-9
a-z 5& 0-9
==> /tmp/F <==
a-z 1& 0-9
a-z 2& 0-9
a-z 3& 0-9
a-z 4& 0-9
a-z 5& 0-9
==> /tmp/L <==
1
4
5
बड़े समय परीक्षण
मैंने बहुत बड़ी फ़ाइलों का एक जोड़ा बनाया:
seq 5000000 | tee /tmp/F |
sort -R | head -n1500000 |
sort -n >/tmp/L
... जो में 5mil लाइनों /tmp/F
और 1.5mil बेतरतीब ढंग से चयनित लाइनों में डाल दिया /tmp/L
। मैंने तब किया:
time \
( export LC_ALL=C
grep -n '' | sort -t: -nmk1,1 ./L - |
sed /:/d\;n | cut -sd: -f2-
) <./F |wc - l
यह मुद्रित:
1500000
grep -n '' \
0.82s user 0.05s system 73% cpu 1.185 total
sort -t: -nmk1,1 /tmp/L - \
0.92s user 0.11s system 86% cpu 1.185 total
sed /:/d\;n \
1.02s user 0.14s system 98% cpu 1.185 total
cut -sd: -f2- \
0.79s user 0.17s system 80% cpu 1.184 total
wc -l \
0.05s user 0.07s system 10% cpu 1.183 total
(मैं वहाँ backslashes जोड़ा)
वर्तमान में यहां दिए गए समाधानों के बीच, यह उन सभी में से सबसे तेज़ है, लेकिन जब मेरी मशीन पर उपर्युक्त डेटासेट के खिलाफ पोज दिया जाता है। दूसरों में से केवल एक ही दूसरे स्थान के लिए चुनाव लड़ने के करीब आया, और वह perl
यहाँ meuh है ।
यह किसी भी तरह से मूल समाधान की पेशकश नहीं है - यह दूसरों द्वारा की पेशकश की सलाह / प्रेरणा के लिए अपने निष्पादन समय का एक तिहाई गिरा दिया है। धीमे समाधान के लिए पोस्ट इतिहास देखें (लेकिन क्यों?) ।
इसके अलावा, यह ध्यान देने योग्य है कि कुछ अन्य उत्तर बहुत अच्छी तरह से बेहतर हो सकते हैं यदि यह मेरे सिस्टम के मल्टी-सीपीयू आर्किटेक्चर और उस पाइपलाइन में प्रत्येक प्रक्रिया के समवर्ती निष्पादन के लिए नहीं थे। वे सभी एक ही समय में काम करते हैं - प्रत्येक अपने स्वयं के प्रोसेसर कोर पर - डेटा के चारों ओर गुजर रहा है और पूरे का अपना छोटा सा हिस्सा कर रहा है। यह बहुत अच्छा है।
लेकिन सबसे तेज़ समाधान है ...
लेकिन यह सबसे तेज समाधान नहीं है। सबसे तेजी से समाधान यहां प्रस्तुत किया गया है, हाथ से नीचे, सी कार्यक्रम है । मैंने उसे फोन किया cselect
। इसे मेरे एक्स क्लिपबोर्ड पर कॉपी करने के बाद, मैंने इसे संकलित किया:
xsel -bo | cc -xc - -o cselect
मैंने तब किया:
time \
./cselect /tmp/L /tmp/F |
wc -l
... और परिणाम थे ...
1500000
./cselect /tmp/L /tmp/F \
0.50s user 0.05s system 99% cpu 0.551 total
wc -l \
0.05s user 0.05s system 19% cpu 0.551 total