将选定的行从一个文件复制到另一个文件

时间:2014-01-08 16:53:38

标签: python file argparse getopt copying

我正在尝试在python中编写一个程序,该程序在txt文件中搜索用户指定的单词,并将包含该单词的选定行复制到另一个文件中。

此外,用户还可以选择排除任何字词。

(例如,假设用户搜索单词“exception”并想要排除单词“abc”,那么代码将只复制其中包含“exception”而不是“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”并搜索“exception”。

但我不知道如何:

  1. 包含多个搜索字词并排除字词
  2. 如何用-e和-s表示它们。我见过argparse和getopt教程。但是没有关于这个特定主题的教程。
  3. 有人可以通过修改我的代码或写一个新代码来帮助我吗?

    这是我现在的代码:

    #/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()
    

1 个答案:

答案 0 :(得分: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循环中,我遍历输入文件中的所有行。然后,我查看inclus_list中的所有单词,并检查它们是否出现在line中。 map function是恕我直言,这是一种优雅的方式;它需要(例如)inclusion_list中的单词,并通过映射 inclusion_list的每个项目到函数lambda x: x in line生成另一个列表。如果输入(True中的一个单词出现在行中),该函数只返回inclusion_list,因此您最终会得到一个True / False项列表。简要说明:

»»» line="foo bar"

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

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

现在我应用any函数来检查inclusion_words_in_line列表中的任何项是否为True,并检查是否有(not any)项目exclusion_words_in_line为True。如果是这种情况,line将附加到输出文件。如果您想确保all中的inclusion_list个字词出现在该行,而不是任何字段(我的问题描述中我不清楚),您可以使用all而不是功能。

请注意,您可以使用环绕inclusion_listexclusion_list的for循环轻松解决上述问题,检查项目是否存在,无需使用mapany