एक पैटर्न में एक बड़ी फ़ाइल को दो भागों में कैसे विभाजित किया जाए?
एक उदाहरण दिया 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/
s
ilently फ़ाइल को विभाजित करेगा , पूर्व f
ix के साथ टुकड़े बनायेगा 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 के -u
nbuffered एक गरीब-गरीब दृष्टिकोण है जो वर्णनकर्ता की ऑफसेट को सुनिश्चित करता है कि जहां कार्यक्रम छोड़ दिया गया है यह - कार्यक्रम के नियमित संचालन को धीमा करने की कोई आवश्यकता नहीं होनी चाहिए - बफरिंग ठीक है - सभी को 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
लाइन को आउटपुट में शामिल किया जाना चाहिए या नहीं?