Domanda

Sto cercando di scrivere un programma in Python che cerca le parole specificate dall'utente in un file TXT e copia le linee selezionate contenenti quella parola in un altro file.

Anche l'utente avrà un'opzione per escludere qualsiasi parola.

(ad es. Supponiamo che l'utente cerca la parola "Eccezione" e vuoi escludere la parola "ABC", quindi il codice copierà solo le linee che ha "Eccezione" in esso ma non "ABC"). Ora tutto il lavoro verrà eseguito dal prompt dei comandi.

L'ingresso sarebbe:

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)
.

Ora l'utente avrà un'opzione per inserire più parole escluse e più parole di ricerca.

Ora finora ho raggiunto che il formato di input è:

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

Esclude la parola "ABC" e cerca "Eccezione".

Ma non so come:

    .
  1. Includi più parole di ricerca multipla ed escludere parole
  2. Come indicarli by -e e -s. Ho visto l'ArgParse e il tutorial Getopt. Ma non c'è tutorial su questo argomento specifico.
  3. Per favore qualcuno può aiutarmi a modificare il mio codice o scrivi uno nuovo?

    Ecco il mio codice di cui ora:

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

    Grazie uomo. Questo mi ha davvero aiutato a capire la logica. Ma sono nuovo a Python, quindi sto ancora avendo alcuni problemi. Quando l'ho eseguito, copia il file con le parole specificate da -s ma non escludono le parole specificate da -e. Che cosa sto facendo di sbagliato? Quindi ecco il mio codice ora: # / 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()
    
    .

È stato utile?

Soluzione

Penso che questo fa ciò che vuoi:

»»» 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'])
.

Se chiami parser.parse_args(), analizzerà gli argomenti passati al tuo script, ma quanto sopra è utile per i test. NOTA Come vengono specificate più ricerche ed escludere parole con più flag -s e -e. Passando action="append" al metodo add_argument, gli argomenti dopo -s e -e vengono aggiunti a un elenco nello spazio dei nomi restituito da parser.parse_args. Questo dovrebbe indirizzare le tue domande 1. e 2..

Ecco un esempio di come è possibile accedere ai valori in un modo carino:

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

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

Ho usato il discarse docs , in particolare Il metodo Add_argument DOC è molto utile.

Modifica: Ecco una funzione che fa la logica di inclusione / esclusione:

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)
.

L'istruzione with garantisce che il file sia correttamente chiuso se qualcosa va storto (vedi doc ). Invece, puoi ovviamente usare lo stesso codice aperto / chiudere già. In effetti, il mio codice non include alcuna gestione degli errori, lo lascerò come esercizio per il lettore. Nel circuito principale for, loopo su tutte le linee nel file di input. Quindi, guardo tutte le parole in Inclusion_List e controlla se si verificano nel line. The map Function è imho un modo elegante per farlo; Ci vogliono (ad esempio) le parole in inclusion_list e genera un altro elenco per mapping ciascuno degli elementi di inclusion_list alla funzione lambda x: x in line. La funzione restituisce solo True se è input (una parola da inclusion_list appare nella riga), quindi si finisce con un elenco di elementi true / falsi. BREVE ESEMPIO:

»»» line="foo bar"

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

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

Ora applico il any funzione per controllare se, bene, Tutti gli articoli nell'elenco inclusion_words_in_line sono veri e per verificare se nessuno (not any) degli elementi in Exclusion_Words_in_line sono true. Se questo è il caso, il line viene aggiunto al file di output. Se si desidera assicurarsi che all delle parole in inclusion_list appaiono sulla linea, piuttosto che di qualsiasi (questo non è stato chiaro dalla descrizione del tuo problema), è possibile utilizzare all funzioni invece.

Nota che è possibile risolvere abbastanza facilmente il sopra con i loop che loop su inclusion_list e exclusion_lists, controllando se gli elementi sono lì, non è necessario utilizzare map e any.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top