2014-01-08 61 views
0

我正在嘗試在python中編寫一個程序,該程序在txt文件中搜索用戶指定的單詞,並將包含該單詞的選定行復制到另一個文件中。將選定的行從一個文件複製到另一個文件

另外,用戶可以選擇排除任何單詞。 (例如,假設用戶搜索單詞「異常」並希望排除單詞「abc」,那麼代碼將只複製其中具有「異常」但不包含「abc」的行)。

現在所有的工作都將在命令提示符下完成。

輸入將是:

file.py test.txt(input file) test_mod.txt(output file) -e abc(exclude word denoted by -e)-s exception(search word denoted by -s) 

現在,用戶將有一個選項,輸入多個排除詞和多個搜索詞。

現在爲止我已經實現了輸入格式爲:

file.py test.txt test_mod.txt abc exception". 

這不包括單詞「ABC」,然後搜索「例外」。

但我不知道如何:

  1. 包括多個搜索詞,並排除的話
  2. 如何通過-e和-s來表示他們。我已經看到了argparse和getopt教程。但沒有關於這個特定主題的教程。

請有人可以幫我修改我的代碼或寫一個新的?

這裏是我的代碼,截至目前:

#/Python33 

import sys 
import os 




def main(): #main method 

try: 

    f1 = open(sys.argv[1], 'r') #takes the first input file in command line 
    found = False 
    user_input1 = (sys.argv[3]) #takes the word which is to be excluded. 
    user_input2 = (sys.argv[4]) #takes the word which is to be included. 
    if sys.argv[1] == sys.argv[2]: 
     f1.close() 
     sys.exit('\nERROR!!\nThe two file names cannot be the same.') 

    if sys.argv[3] != sys.argv[4]: 

    for line in f1: 

     if user_input1 in line or user_input2 in line: 

      f2 = open(sys.argv[2], 'a') 

      if user_input1 in line: 
       if user_input2 in line: 
        pass 

      elif user_input2 in line: 
       f2.write(line) 
       found = True 
       f2.close() 


    if not found: 
     print("ERROR: The Word couldn't be found.")    



    f1.close() 


    if sys.argv[3] == sys.argv[4]: 
     f1.close() 
     sys.exit('\nERROR!!\nThe word to be excluded and the word to be included cannot be the same.') 



except IOError: 
     print('\nIO error or wrong file name.') 
except IndexError: 
     print('\nYou must enter 5 parameters.') #prevents less than 5 inputs which is mandatory 
except SystemExit as e:      #Exception handles sys.exit() 
     sys.exit(e) 


if __name__ == '__main__': 
    main() 

感謝的人。這真的幫助我理解邏輯。但我是python的新手,所以我仍然遇到一些問題。每當我運行它時,它都會使用-s指定的文字複製文件,但不排除由-e指定的文字。我究竟做錯了什麼?因此,這裏是我現在的代碼: #/ Python33

#takes a text file, finds a word and writes that line containing that word but not a 2nd word specified by the user. So if both of them are there, that line is not printed 

import sys 
import os 
import argparse 



def main(): #main method 

try: 

    parser = argparse.ArgumentParser(description='Copies selected lines from files') 
    parser.add_argument('input_file') 
    parser.add_argument('output_file') 
    parser.add_argument('-e',action="append") 
    parser.add_argument('-s',action="append") 
    args = parser.parse_args('test.txt, test_mod.txt, -e , -s exception'.split()) 


    user_input1 = (args.e) #takes the word which is to be excluded. 
    user_input2 = (args.s) #takes the word which is to be included. 

    def include_exclude(input_file, output_file, exclusion_list=[], inclusion_list=[]): 


     with open(output_file, 'w') as fo: 
     with open(input_file, 'r') as fi: 
      for line in fi: 
       inclusion_words_in_line = map(lambda x: x in line, inclusion_list) 
       exclusion_words_in_line = map(lambda x: x in line, exclusion_list) 
       if any(inclusion_words_in_line) and not any(exclusion_words_in_line): 
        fo.write(line)  
    if user_input1 != user_input2 : 
     include_exclude('test.txt', 'test_mod.txt', user_input1, user_input2); 
     print("hello") 

    if user_input1 == user_input2 : 


     sys.exit('\nERROR!!\nThe word to be excluded and the word to be included cannot be the same.') 



except IOError: 
     print('\nIO error or wrong file name.') 
except IndexError: 
     print('\nYou must enter 5 parameters.') 
except SystemExit as e:      
     sys.exit(e) 


if __name__ == '__main__': 
    main() 
+0

我不得不清理縮進一點,但你的代碼對我來說工作得很好(包括和不包括)。你忘了把'parser.parse_args('test ...)'改回'parser.parse_args()'並且同樣改變'test.txt'和'test_mod.txt'? – kalhartt

回答

0

我想這你想要做什麼:

»»» import argparse 

»»» parser = argparse.ArgumentParser(description='foo baaar') 

»»» parser.add_argument('input_file') 
Out[3]: _StoreAction(option_strings=[], dest='input_file', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) 

»»» parser.add_argument('output_file') 
Out[4]: _StoreAction(option_strings=[], dest='output_file', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) 

»»» parser.add_argument('-e', action="append") 
Out[5]: _AppendAction(option_strings=['-e'], dest='e', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) 

»»» parser.add_argument('-s', action="append") 
Out[6]: _AppendAction(option_strings=['-s'], dest='s', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None) 

»»» parser.parse_args('foo1.txt foo2.txt -e abc -e def -s xyz -s pqr'.split()) 
Out[7]: Namespace(e=['abc', 'def'], input_file='foo1.txt', output_file='foo2.txt', s=['xyz', 'pqr']) 

如果你只需要調用parser.parse_args(),它將解析傳遞給腳本的參數,但以上方便測試。請注意,如何使用多個-s-e標誌指定多個搜索和排除詞。通過將action="append"傳遞給add_argument方法,將-s-e之後的參數添加到由parser.parse_args返回的名稱空間中的列表中。這應該解決您的問題1.2.

這裏是如何在一個不錯的方式訪問該值的示例:

»»» args = parser.parse_args('foo1.txt foo2.txt -e abc -e def -s xyz -s pqr'.split()) 

»»» args.e 
Out[12]: ['abc', 'def'] 

我用了argparse docs,尤其是the add_argument method doc是非常有用的。

編輯:這裏有一個函數,它包含/排除邏輯:

def include_exclude(input_file, output_file, inclusion_list, exclusion_list=[]): 
    with open(output_file, 'w') as fo: 
     with open(input_file, 'r') as fi: 
      for line in fi: 
       inclusion_words_in_line = map(lambda x: x in line, inclusion_list) 
       exclusion_words_in_line = map(lambda x: x in line, exclusion_list) 
       if any(inclusion_words_in_line) and not any(exclusion_words_in_line): 
        fo.write(line) 

with語句確保如果出現任何錯誤(見doc),該文件被正確關閉。相反,你當然可以使用你已經擁有的相同的開啓/關閉代碼。事實上,我的代碼不包含任何錯誤處理,我將其作爲讀者的練習。在主要的for循環中,我遍歷輸入文件中的所有行。然後,我查看包含列表中的所有單詞,並檢查它們是否發生在line中。 map function是恕我直言的一個優雅的方式做到這一點;它需要(例如)inclusion_list中的單詞,並且通過生成另一個列表將每個inclusion_list的項目映射到函數lambda x: x in line。如果輸入該函數(inclusion_list中的一個單詞出現在該行中),則該函數僅返回True,因此最終會顯示True/False項目的列表。簡單的例子:

»»» line="foo bar" 

»»» words=['foo', 'barz'] 

»»» map(lambda x: x in line, words) 
Out[24]: [True, False] 

現在我應用any功能檢查,那麼,任何在inclusion_words_in_line列表中的項目都是真實的,並檢查是否在exclusion_words_in_line項目的無(not any)是正確的。如果是這種情況,則將line附加到輸出文件。如果您想確保inclusion_list中的字詞出現在all之內,而不是任何(您在問題描述中對此不清楚),則可以使用all函數代替。

注意,你可以很容易地解決上述與循環,即環比inclusion_listexclusion_list S,如果檢查的項目有沒有,有沒有必要使用mapany

+0

該代碼將-e和-s表示的詞分開,但我的目標是從文本文件中讀取並將選定的行復制到新文件中,該文件也將被創建。這意味着這些行包含表示的詞as -s在命令提示符中,但不由-e.So假設(test.txt)包含兩行:1.這是一個帶有exception.2.abc異常的文件。當我輸入命令提示符時:file.py test .txt test_mod.txt -e abc -s異常,將會創建一個名爲「test_mod.txt」的新文件,其行名爲「這是一個有例外的文件」。並且我還可以輸入多個-e或-s提示。我該怎麼做 – sagarnildass

+0

'm01'給你的不是完全替代你的代碼。它只是取代了直接訪問'sys.argv [n]'。即用'args.input_file'替換'sys.argv [1]',用'args.out_file'替換'sys.argv [2]','user_input1 = args.e'(除了現在是單詞列表,只有一個)。 – hpaulj

+0

我以爲你已經完成了搜索。現在您可以獲得包含/排除詞的列表,您可能想嘗試改變您的代碼來解釋這一點。我會編輯帖子以說明如何做到這一點,以防萬一你卡住了。 – m01

相關問題