एक पैटर्न में एक बड़ी फ़ाइल को दो भागों में कैसे विभाजित किया जाए?
एक उदाहरण दिया file.txt:
ABC
EFG
XYZ
HIJ
KNL
मैं इस फाइल को XYZइस तरह से विभाजित करना चाहता हूं file1जिसमें लाइन अप और टू XYZऔर बाकी लाइनें शामिल हों file2।
एक पैटर्न में एक बड़ी फ़ाइल को दो भागों में कैसे विभाजित किया जाए?
एक उदाहरण दिया file.txt:
ABC
EFG
XYZ
HIJ
KNL
मैं इस फाइल को XYZइस तरह से विभाजित करना चाहता हूं file1जिसमें लाइन अप और टू XYZऔर बाकी लाइनें शामिल हों file2।
जवाबों:
साथ awkआप कर सकते हैं:
awk '{print >out}; /XYZ/{out="file2"}' out=file1 largefile
स्पष्टीकरण: पहला awkतर्क ( out=file1) फ़ाइल नाम के साथ एक चर को परिभाषित करता है जिसका उपयोग आउटपुट के लिए किया जाएगा जबकि बाद के तर्क ( largefile) को संसाधित किया जाता है। awkकार्यक्रम चर द्वारा निर्दिष्ट फ़ाइल के लिए सभी लाइनों प्रिंट होगा out( {print >out})। यदि पैटर्न XYZमिल जाएगा आउटपुट चर को नई फ़ाइल ( {out="file2}") में इंगित करने के लिए पुनर्परिभाषित किया जाएगा जो बाद की डेटा लाइनों को प्रिंट करने के लिए लक्ष्य के रूप में उपयोग किया जाएगा।
संदर्भ:
यह इसके लिए एक काम है csplit:
csplit -sf file -n 1 large_file /XYZ/
silently फ़ाइल को विभाजित करेगा , पूर्व fix के साथ टुकड़े बनायेगा fileऔर nएकल अंक, उदाहरण file0आदि का उपयोग करके umbered । ध्यान दें कि उपयोग /regex/करने से विभाजित होगा, लेकिन उस रेखा से मेल नहीं खाता है जिसमें मेल खाता है regex। अप करने के लिए विभाजित करने के लिए और लाइन मिलान सहित regexजोड़ने एक +1ऑफसेट:
csplit -sf file -n 1 large_file /XYZ/+1
यह दो फाइलें बनाता है, file0और file1। यदि आपको उनके नाम की आवश्यकता है file1और file2आप हमेशा csplitकमांड में एक खाली पैटर्न जोड़ सकते हैं और पहली फाइल को हटा सकते हैं:
csplit -sf file -n 1 large_file // /XYZ/+1
बनाता है file0, file1और file2लेकिन file0खाली है ताकि आप उसे सुरक्षित निकाल सकते हैं:
rm -f file0
ऊपर दिए गए एक उत्तर में एक आधुनिक के साथ एक kshशैल संस्करण (अर्थात बिना sed)sed
{ read in <##XYZ ; print "$in" ; cat >file2 ;} <largefile >file1
और kshअकेले में एक और संस्करण (यानी भी omitting cat):
{ read in <##XYZ ; print "$in" ; { read <##"" ;} >file2 ;} <largefile >file1
(शुद्ध kshसमाधान काफी अच्छा प्रतीत होता है; 2.4 जीबी परीक्षण फ़ाइल पर इसे 19-21 सेकंड की आवश्यकता थी, जबकि 39-47 सेकंड sed/ catआधारित दृष्टिकोण के साथ)।
readऔर printआपको इसे केवल अपने स्वयं के आउटपुट पर जाने देना चाहिए। प्रदर्शन बेहतर हो जाता है यदि आप एएसटी टूलकिट को पूरी तरह से बनाते हैं और सभी kshसंकलित निर्माणों को प्राप्त करते हैं - यह मेरे लिए अजीब है जो sedवास्तव में उनमें से एक नहीं है। लेकिन जैसे सामान के साथ while <file doमुझे लगता है कि आपको sedइतनी ज़रूरत नहीं है ...
awkआपके बेंचमार्क में कैसा प्रदर्शन रहा? और जब मुझे पूरा यकीन है कि kshसंभावना हमेशा इस लड़ाई को जीतेगी, अगर आप एक GNU का उपयोग कर रहे हैं, तो आप sedबहुत निष्पक्ष नहीं हो रहे हैं sed- GNU के -unbuffered एक गरीब-गरीब दृष्टिकोण है जो वर्णनकर्ता की ऑफसेट को सुनिश्चित करता है कि जहां कार्यक्रम छोड़ दिया गया है यह - कार्यक्रम के नियमित संचालन को धीमा करने की कोई आवश्यकता नहीं होनी चाहिए - बफरिंग ठीक है - सभी को sedकरना होगा जब समाप्त हो जाए तो विवरणक को lseek करना होगा। जिस कारण से GNU उस मानसिकता को उलट देता है।
while; मुद्रण को मूल रूप से <##पुनर्निर्देशन ऑपरेटर के परिभाषित दुष्प्रभाव के रूप में किया जाता है । और केवल मिलान रेखा को मुद्रण की आवश्यकता होती है। (इस तरह से शेल फीचर का कार्यान्वयन incl./excl के समर्थन के लिए सबसे अधिक लचीला है।) एक स्पष्ट whileलूप मैं महत्वपूर्ण धीमी होने की उम्मीद करूँगा (लेकिन जाँच नहीं की गई)।
headबजाय की कोशिश की read; यह केवल थोड़ा धीमा लगता है, लेकिन यह बहुत ही कठिन है { head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3:।
एक आसान हैक या तो STDOUT या STDERR को प्रिंट करना है, यह इस बात पर निर्भर करता है कि लक्ष्य पैटर्न का मिलान किया गया है या नहीं। फिर आप अपने अनुसार आउटपुट को पुनर्निर्देशित करने के लिए शेल के पुनर्निर्देशन ऑपरेटरों का उपयोग कर सकते हैं । उदाहरण के लिए, पर्ल में, इनपुट फ़ाइल को कहा जाता है fऔर दो आउटपुट फाइल f1और f2:
विभाजन पैटर्न से मेल खाने वाली रेखा के बारे में:
perl -ne 'if(/XYZ/){$a=1; next} ; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2मिलान लाइन सहित:
perl -ne '$a=1 if /XYZ/; $a==1 ? print STDERR : print STDOUT;' f >f1 2>f2वैकल्पिक रूप से, विभिन्न फ़ाइल हैंडल पर प्रिंट करें:
विभाजन पैटर्न से मेल खाने वाली रेखा के बारे में:
perl -ne 'BEGIN{open($fh1,">","f1");open($fh2,">","f2");}
if(/XYZ/){$a=1; next}$a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
मिलान लाइन सहित:
perl -ne 'BEGIN{open($fh1,">","f1"); open($fh2,">","f2");}
$a=1 if /XYZ/; $a==1 ? print $fh1 "$_" : print $fh2 "$_";' f
XYZलाइन को आउटपुट में शामिल किया जाना चाहिए या नहीं?