2012-10-06 13 views
9

मेरे पास ~ 200 छोटी टेक्स्ट फ़ाइलें (50 केबी) हैं जिनके पास एक समान प्रारूप है। मैं उन फ़ाइलों में से प्रत्येक पंक्ति में एक रेखा खोजना चाहता हूं जिसमें एक निश्चित स्ट्रिंग है और उसके बाद उस पंक्ति को अगली तीन पंक्तियां (लेकिन फ़ाइल में शेष पंक्तियों में नहीं) को दूसरी टेक्स्ट फ़ाइल में लिखें। मैं ऐसा करने के लिए खुद को पाइथन सिखाने की कोशिश कर रहा हूं और इसे आजमाने के लिए एक बहुत ही सरल और कच्ची छोटी लिपि लिखी है। मैं संस्करण 2.6.5 का उपयोग कर रहा है, और मैक टर्मिनल से स्क्रिप्ट चलाने:एक फ़ाइल से दूसरी फ़ाइल में विशिष्ट लाइनों को लिखने के लिए पायथन का उपयोग

#!/usr/bin/env python 

f = open('Test.txt') 

Lines=f.readlines() 
searchquery = 'am\n' 
i=0 

while i < 500: 
    if Lines[i] == searchquery: 
     print Lines[i:i+3] 
     i = i+1 
    else: 
     i = i+1 
f.close() 

यह कम या ज्यादा काम करता है और स्क्रीन पर उत्पादन प्रिंट करता है। लेकिन मैं बजाय एक नई फ़ाइल में लाइनों प्रिंट करना चाहते हैं, तो मैं कुछ इस तरह की कोशिश की:

f1 = open('Test.txt') 
f2 = open('Output.txt', 'a') 

Lines=f1.readlines() 
searchquery = 'am\n' 
i=0 

while i < 500: 
if Lines[i] == searchquery: 
    f2.write(Lines[i]) 
    f2.write(Lines[i+1]) 
    f2.write(Lines[i+2]) 
    i = i+1 
else: 
    i = i+1 
f1.close() 
f2.close() 

हालांकि, कुछ भी नहीं फाइल करने के लिए लिखा है। मैंने

from __future__ import print_function 
print(Lines[i], file='Output.txt') 

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

धन्यवाद, और खेद है कि यह एक सुपर मूल प्रश्न है!

+2

दूसरे उदाहरण में, ऐसा लगता है कि आपका लूप बॉडी इंडेंट नहीं है .. क्या यह एक प्रतिलिपि/पेस्ट त्रुटि या वास्तव में आपके पास है? – Collin

+2

आपको शायद 'एन्युमेरेट' फ़ंक्शन और 'एक्स में इरिएबल' निर्माण के लिए देखना चाहिए। –

+0

@ कोलिन आप सही हैं समस्या यह इंडेंटेशन थी।मैंने शायद उस कोड को दो घंटे तक देखा और कभी नहीं देखा! धन्यवाद! – Andreanna

उत्तर

17

रूप @ajon से कहा, मैं वहाँ कुछ भी खरोज को छोड़कर अपने कोड के साथ मौलिक रूप से गलत है नहीं लगता है:

आप इंडेंट करने के लिए इस तरह के रूप i=i+1 अगर Lines[i] से जब तक के बाद की जरूरत है। इंडेंटेशन फिक्स्ड के साथ यह मेरे लिए काम करता है। हालांकि सुधार के लिए कुछ अवसर हैं।

1) पायथन में, चीजों पर पुनरावृत्ति का मानक तरीका for loop का उपयोग कर है। for लूप का उपयोग करते समय, आपको लूप काउंटर वैरिएबल को परिभाषित करने की आवश्यकता नहीं है और चीजों को फिर से चलाने के लिए स्वयं का ट्रैक रखें। इसके बजाए, आप इस

for line in lines: 
    print line 

स्ट्रिंग की सूची में सभी आइटमों को फिर से भरने और उन्हें प्रिंट करने के लिए कुछ लिखते हैं।

2) ज्यादातर मामलों में यह आपके for लूप जैसा दिखता है। हालांकि, ऐसी स्थितियां हैं जहां आप वास्तव में लूप गिनती का ट्रैक रखना चाहते हैं। आपका मामला ऐसी स्थिति है, क्योंकि आपको न केवल उस पंक्ति की आवश्यकता है बल्कि अगले तीन भी चाहिए, और इसलिए अनुक्रमण के लिए काउंटर का उपयोग करने की आवश्यकता है (lst[i])। इसके लिए enumerate() है, जो और आइटमों की एक सूची वापस लौटाएगा, जिन पर आप लूप कर सकते हैं।

for i, line in enumerate(lines): 
    print i 
    print line 
    print lines[i+7] 

हैं यदि आप स्वयं अपनी उदाहरण के रूप में पाश काउंटर का ट्रैक रखने के थे, वहाँ दो चीजें है:

3)i = i+1 कि if और else ब्लॉक से बाहर ले जाया जाना चाहिए। आप इसे दोनों मामलों में कर रहे हैं, इसलिए इसे if/else के बाद रखें। आपके मामले में else ब्लॉक तो किसी भी अधिक कुछ भी नहीं है, और समाप्त किया जा सकता:

while i < 500: 
    if Lines[i] == searchquery: 
     f2.write(Lines[i]) 
     f2.write(Lines[i+1]) 
     f2.write(Lines[i+2]) 
    i = i+1 

4) अब, यह 500 लाइनों की तुलना में कम फाइलों के साथ एक IndexError का कारण होगा। 500 की लूप गणना को हार्ड कोडिंग करने के बजाय, आपको उस अनुक्रम की वास्तविक लंबाई का उपयोग करना चाहिए जिस पर आप पुन: प्रयास कर रहे हैं। len(lines) आपको वह लंबाई देगा। लेकिन while लूप का उपयोग करने के बजाय, for लूप और range(len(lst)) का उपयोग शून्य से len(lst) - 1 तक की श्रेणी की सूची में फिर से करने के लिए करें।

for i in range(len(lst)): 
    print lst[i] 

5)open() एक context manager है कि आप के लिए फ़ाइलों को बंद करने का ख्याल रखता है के रूप में इस्तेमाल किया जा सकता। संदर्भ प्रबंधक एक उन्नत अवधारणा हैं लेकिन यदि वे पहले से ही आपके लिए उपलब्ध कराए गए हैं तो इसका उपयोग करना बहुत आसान है। इस

with open('test.txt') as f: 
    f.write('foo') 

की तरह कुछ करने से फ़ाइल f कि with ब्लॉक के अंदर के रूप में खोला जाएगा और सुलभ आप के लिए। ब्लॉक छोड़ने के बाद फ़ाइल स्वचालित रूप से बंद हो जाएगी, इसलिए आप फ़ाइल को बंद करने के लिए भूलना समाप्त नहीं कर सकते हैं।

आपके मामले में आप दो फाइलें खोल रहे हैं। यह सिर्फ दो with बयानों और घोंसला का उपयोग करके किया जा सकता है उन्हें

with open('one.txt') as f1: 
    with open('two.txt') as f2: 
     f1.write('foo') 
     f2.write('bar') 

या, अजगर 2.7 में/अजगर 3.x, एक भी with बयान में दो संदर्भ प्रबंधक घोंसले बनाने:

with open('one.txt') as f1, open('two.txt', 'a') as f2: 
     f1.write('foo') 
     f2.write('bar') 

6) ऑपरेटिंग सिस्टम के आधार पर फ़ाइल बनाई गई थी, लाइन एंडिंग अलग हैं। यूनिक्स-जैसे प्लेटफ़ॉर्म पर यह \n है, ओएस एक्स से पहले मैक \r का उपयोग करता है, और विंडोज \r\n का उपयोग करता है। तो Lines[i] == searchquery मैक या विंडोज लाइन के अंत तक मेल नहीं खाएगा। file.readline() सभी तीनों से निपट सकता है, लेकिन क्योंकि यह लाइन के अंत में जो लाइन लाइन समाप्त होता है, तुलना विफल हो जाएगी।

searchquery = 'am' 
# ... 
      if line.strip() == searchquery: 
       # ... 

(file.read() का उपयोग कर फ़ाइल को पढ़ने और: यह str.strip() का उपयोग, जो शुरुआत और अंत में सभी खाली स्थान के की स्ट्रिंग पट्टी जाएगा, और लाइन है कि करने के लिए न खत्म होने वाली बिना एक खोज पैटर्न तुलना द्वारा हल किया जाता है str.splitlines() का उपयोग करना एक और विकल्प होगा।)

लेकिन, जब से तुम अपनी खोज स्ट्रिंग वास्तव में उल्लेख किया है पंक्ति के आरंभ में प्रकट होता है, देता है कि करते हैं, str.startswith() का उपयोग करके:

if line.startswith(searchquery): 
    # ... 

7) अजगर, PEP8 के लिए सरकारी गाइड शैली, कक्षाओं के लिए CamelCase का उपयोग करने की सिफारिश करता है, lowercase_underscore बहुत अधिक सब कुछ (चर, कार्य, गुण, विधियों, मॉड्यूल, पैकेज) के लिए। तो Lines के बजाय lines का उपयोग करें। यह निश्चित रूप से दूसरों की तुलना में एक मामूली बिंदु है, लेकिन अभी भी ठीक से शुरू करने लायक है।


तो, उन सभी चीज़ों पर विचार मैं इस तरह अपने कोड लिखने होगा:

searchquery = 'am' 

with open('Test.txt') as f1: 
    with open('Output.txt', 'a') as f2: 
     lines = f1.readlines() 
     for i, line in enumerate(lines): 
      if line.startswith(searchquery): 
       f2.write(line) 
       f2.write(lines[i + 1]) 
       f2.write(lines[i + 2]) 

@TomK के रूप में बताया, यह सब कोड मानती है कि आपके खोज स्ट्रिंग मेल खाता है, यह है कि कम से कम दो लाइनों इसके बाद यदि आप उस धारणा पर भरोसा नहीं कर सकते हैं, तो try...except ब्लॉक का उपयोग करके उस मामले से निपटने के लिए @poorsod सुझाव दिया गया है कि यह सही तरीका है।

+2

वाह, यह अविश्वसनीय रूप से सहायक है। विस्तृत स्पष्टीकरण के लिए धन्यवाद! – Andreanna

2

मुझे लगता है कि आपकी समस्या नीचे फ़ाइल का टैब है।

while i < 500: 
    if Lines[i] == searchquery: 
     f2.write(Lines[i]) 
     f2.write(Lines[i+1]) 
     f2.write(Lines[i+2]) 
     i = i+1 
    else: 
     i = i+1 
1

अजोन का सही उत्तर है, लेकिन जब तक आप मार्गदर्शन की तलाश में हैं, तो आपका समाधान उच्च स्तर की संरचनाओं का लाभ नहीं उठाता है जो पायथन ऑफर कर सकते हैं। कैसे:

searchquery = 'am\n' 

with open('Test.txt') as f1: 
    with open(Output.txt, 'a') as f2: 

    Lines = f1.readlines() 

    try: 
     i = Lines.index(searchquery) 
     for iline in range(i, i+3): 
     f2.write(Lines[iline]) 
    except: 
     print "not in file" 

दो "साथ" कथन स्वचालित रूप से अंत में फ़ाइलों को बंद कर देंगे, भले ही अपवाद होता है।

एक अभी भी बेहतर समाधान, लाइन द्वारा प्रक्रिया लाइन ही बार में पूरा फ़ाइल में पढ़ने से बचने के लिए होगा (जो जानता है कि यह कितना बड़ा हो सकता है?) और, बजाय, एक फ़ाइल वस्तु पर यात्रा का उपयोग कर:

with open('Test.txt') as f1: 
    with open(Output.txt, 'a') as f2: 
     for line in f1: 
     if line == searchquery: 
      f2.write(line) 
      f2.write(f1.next()) 
      f2.write(f1.next()) 

ये सभी मानते हैं कि आपकी लक्षित रेखा से कम से कम दो अतिरिक्त लाइनें हैं।

+0

"ये सभी मानते हैं कि आपकी लक्षित रेखा से कम से कम दो अतिरिक्त लाइनें हैं।" - यह इंगित करने लायक है कि इस स्थिति से निपटने का तरीका एक 'प्रयास करें ...' ब्लॉक को छोड़कर] (http://docs.python.org/reference/compound_stmts.html#the-try-statement) : 'कोशिश करें: f2.write (f1.next()); StopIteration को छोड़कर: पास 'या इसी तरह। –

+0

आपको never_ का उपयोग नंगे 'को छोड़कर करना चाहिए:' कथन, हमेशा उन अपवादों को सूचीबद्ध करें जिन्हें आप स्पष्ट रूप से पकड़ना चाहते हैं (इस मामले में 'इंडेक्स त्रुटि')। एक नंगे 'को छोड़कर:' उन चीज़ों को पकड़ने का कारण बन सकता है जिन्हें आप _didn't_ सोचते हैं, और जिस मामले की आप अपेक्षा कर रहे थे, उसे अलग-अलग संभालने की आवश्यकता है। उस स्थिति में अपवाद उठाया जाना चाहिए, जिससे आपका कोड जारी रखने और संभावित रूप से क्षति पहुंचाने के बजाए रुकने का कारण बनता है। –

1

क्या आपने समस्या के रूप में किसी भी फाइल सिस्टम से संबंधित मुद्दों से बचने के लिए 'आउटपुट.txt' के अलावा कुछ और करने का प्रयास किया है?

इसका निदान करते समय किसी भी भयानक अप्रत्याशित समस्याओं से बचने के लिए एक पूर्ण पथ के बारे में क्या।

यह सलाह केवल नैदानिक ​​दृष्टिकोण से है। ओएस एक्स dtrace और dtruss भी देखें।

देखें: Equivalent of strace -feopen <command> on mac os X

0

लेखन लाइन लाइन द्वारा धीमी गति से जब बड़े डेटा के साथ काम हो सकता है। आप एक बार में लाइनों का एक समूह पढ़ने/लिखकर पढ़ने/लिखने के संचालन को तेज कर सकते हैं।

from itertools import slice 

f1 = open('Test.txt') 
f2 = open('Output.txt', 'a') 

bunch = 500 
lines = list(islice(f1, bunch)) 
f2.writelines(lines) 

f1.close() 
f2.close() 

मामले में अपने लाइनों बहुत लंबा है और अपने सिस्टम के आधार पर, आप एक सूची में 500 लाइनों डाल करने के लिए सक्षम नहीं हो सकता है। यदि ऐसा है, तो आपको bunch आकार को कम करना चाहिए और पूरी चीज़ लिखने के लिए आवश्यकतानुसार पढ़ने/लिखने के चरणों को कम करना चाहिए।

संबंधित मुद्दे

 संबंधित मुद्दे