मेरे पास एक फाइल है जिसमें लगभग 10 मिलियन लाइनें हैं।
मैं फ़ाइल में सभी पंक्तियों को निकालना चाहता हूं जो छह वर्णों से कम हैं।
मैं यह कैसे करु?
मेरे पास एक फाइल है जिसमें लगभग 10 मिलियन लाइनें हैं।
मैं फ़ाइल में सभी पंक्तियों को निकालना चाहता हूं जो छह वर्णों से कम हैं।
मैं यह कैसे करु?
जवाबों:
इसे करने के कई तरीके हैं।
का उपयोग कर grep
:
grep -E '^.{6,}$' file.txt >out.txt
अब out.txt
छह या अधिक वर्ण वाली रेखाएँ होंगी।
रिवर्स तरीका:
grep -vE '^.{,5}$' file.txt >out.txt
sed
5 या उससे कम लंबाई वाली रेखाओं का उपयोग करना :
sed -r '/^.{,5}$/d' file.txt
रिवर्स तरीका, लंबाई छह या अधिक की छपाई लाइनें:
sed -nr '/^.{6,}$/p' file.txt
आप का उपयोग कर एक अलग फाइल में उत्पादन को बचा सकता है >
की तरह ऑपरेटर grep
या संपादित यथा-स्थान का उपयोग कर फ़ाइल -i
का विकल्प sed
:
sed -ri.bak '/^.{6,}$/' file.txt
मूल फ़ाइल के रूप में बैकअप किया जाएगा file.txt.bak
और संशोधित फ़ाइल होगी file.txt
।
यदि आप बैकअप नहीं रखना चाहते हैं:
sed -ri '/^.{6,}$/' file.txt
शेल का उपयोग करना, धीमा करना, ऐसा न करना , यह सिर्फ एक और तरीका दिखाने के लिए है:
while IFS= read -r line; do [ "${#line}" -ge 6 ] && echo "$line"; done <file.txt
का उपयोग करते हुए python
, यहां तक कि धीमी गति से grep
, sed
:
#!/usr/bin/env python2
with open('file.txt') as f:
for line in f:
if len(line.rstrip('\n')) >= 6:
print line.rstrip('\n')
अधिक पायथोनिक होने के लिए बेहतर उपयोग सूची की समझ:
#!/usr/bin/env python2
with open('file.txt') as f:
strip = str.rstrip
print '\n'.join([line for line in f if len(strip(line, '\n')) >= 6]).rstrip('\n')
यह बहुत सरल है:
grep ...... inputfile > resultfile #There are 6 dots
यह अत्यंत कुशल है, क्योंकि grep
यह जरूरत से ज्यादा पार्स करने की कोशिश नहीं करेगा, न ही किसी भी तरह से वर्णों की व्याख्या करने के लिए: यह बस एक (पूरी) पंक्ति को stdout (जो शेल फिर परिणाम को रीडायरेक्ट करता है) को भेज देता है जैसे ही वह 6 उस लाइन पर चार्ट ( .
एक regexp संदर्भ में किसी भी 1 वर्ण से मेल खाता है)।
इसलिए grep केवल 6 (या अधिक) वर्ण वाली आउटपुट लाइनें होगी, और अन्य grep द्वारा आउटपुट नहीं किए जाते हैं, इसलिए वे इसे परिणामी नहीं बनाते हैं।
सबसे तेज़ तरीका: इस C प्रोग्राम को संकलित करें और चलाएं:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_BUFFER_SIZE 1000000
int main(int argc, char *argv[]) {
int length;
if(argc == 3)
length = atoi(argv[2]);
else
return 1;
FILE *file = fopen(argv[1], "r");
if(file != NULL) {
char line[MAX_BUFFER_SIZE];
while(fgets(line, sizeof line, file) != NULL) {
char *pos;
if((pos = strchr(line, '\n')) != NULL)
*pos = '\0';
if(strlen(line) >= length)
printf("%s\n", line);
}
fclose(file);
}
else {
perror(argv[1]);
return 1;
}
return 0;
}
के साथ संकलित करें gcc program.c -o program
, ./program file line_length
(जहाँ file
= फ़ाइल के लिए पथ और line_length
= न्यूनतम पंक्ति लंबाई, आपके मामले में)6
, अधिकतम पंक्ति की लंबाई 1000000
प्रति पंक्ति वर्णों तक सीमित है ; आप इसे बदल सकते हैं MAX_BUFFER_SIZE
)।
( पाया के \n
साथ स्थानापन्न करने की ट्रिक\0
यहाँ ।)
शेल समाधान को छोड़कर इस प्रश्न के लिए प्रस्तावित सभी अन्य समाधानों के साथ तुलना करें (8 वर्णों की औसत लेन के साथ 10M लाइनों के साथ ~ 91MB फ़ाइल पर परीक्षण चलाएं):
time ./foo file 6
real 0m1.592s
user 0m0.712s
sys 0m0.160s
time grep ...... file
real 0m1.945s
user 0m0.912s
sys 0m0.176s
time grep -E '^.{6,}$'
real 0m2.178s
user 0m1.124s
sys 0m0.152s
time awk 'length>=6' file
real 0m2.261s
user 0m1.228s
sys 0m0.160s
time perl -lne 'length>=6&&print' file
real 0m4.252s
user 0m3.220s
sys 0m0.164s
sed -r '/^.{,5}$/d' file >out
real 0m7.947s
user 0m7.064s
sys 0m0.120s
./script.py >out
real 0m8.154s
user 0m7.184s
sys 0m0.164s
awk 'length>=6' file
length>=6
: अगर length>=6
TRUE लौटाता है, तो वर्तमान रिकॉर्ड को प्रिंट करता है।perl -lne 'length>=6&&print' file
lenght>=6
TRUE लौटाता है, तो वर्तमान रिकॉर्ड को प्रिंट करता है।% cat file
a
bb
ccc
dddd
eeeee
ffffff
ggggggg
% ./foo file 6
ffffff
ggggggg
% awk 'length>=6' file
ffffff
ggggggg
% perl -lne 'length>=6&&print' file
ffffff
ggggggg
awk
sed
समाधान को हटाना पड़ा (ऐसा होता है, मुझे पता है)। XD
pos
चर का बिंदु क्या है ? मुझे लगता है कि यह line
एक नई चरित्र के साथ चरित्र को एक पॉइंटर देता है , लेकिन आप इसका उपयोग कभी नहीं करते हैं। और अगर आपको यह नहीं मिलता है, तो आप इसे इसके बराबर सेट करते हैं \0
।
\0
( strchr()
यदि चरित्र नहीं मिला है तो एक पूर्ण सूचक देता है )। बिंदु प्रत्येक पंक्ति के अंत में प्रत्येक नई पंक्ति की जगह ले रहा है \0
ताकि नई रेखा को कभी भी गिना न जाए strlen()
: यह इसलिए है ताकि अंतिम पंक्ति पर संभावित लापता नई रेखा की परवाह किए बिना हमेशा 6 की तुलना की जा सके। अलग तरह से केवल अंतिम पंक्ति का इलाज करना अधिक कुशल होगा, मुझे पता है। मैं शायद इसे बाद में अपडेट करूंगा।
grep
उसी फ़ाइल पर समाधान का परीक्षण किया और यह वास्तव में तेज़ है (शायद इसलिए strlen()
कि यह सबसे अच्छा विचार नहीं है) । मैं getchar()
इसके बजाय केवल पहले N वर्ण की जाँच करने के लिए लूप का उपयोग करने की कोशिश करूँगा , मुझे लगता है कि इसे दृष्टिगत रूप से सुधारना चाहिए। और हां, बफ़र की लंबाई के ऊपर कोई भी लाइन बस बफ़र की लंबाई तक कट जाती है।
आप पूर्व मोड में विम का उपयोग कर सकते हैं:
ex -sc 'v/\v.{6}/d' -cx file
\v
जादू चालू करो
.{6}
6 या अधिक वर्णों वाली लाइनें ढूंढें
v
चयन को उल्टा करें
d
हटाना
x
सहेजें और बंद करें
रूबी समाधान:
$ cat input.txt
abcdef
abc
abcdefghijk
$ ruby -ne 'puts $_ if $_.chomp.length() >= 6 ' < input.txt
abcdef
abcdefghijk
सरल विचार: रूबी की स्टडिन में फ़ाइल को रीडायरेक्ट करें, और स्टडिन से प्रिंट लाइन केवल अगर यह लंबाई अधिक या 6 के बराबर हो