Как расширить этот скрипт Python поиска и замены, чтобы принимать переменные из командной строки? - PullRequest
2 голосов
/ 22 июля 2011

В настоящее время у меня есть скрипт, который делает следующее.Если у меня есть текстовый файл со строками:

<<Name>> is at <<Location>>.
<<Name>> is feeling <<Emotion>>.

Сценарий примет этот входной файл в качестве аргумента командной строки и запросит у пользователя переменные:

Name? Bob
Location? work
Emotion? frustrated

Примечаниеэто имя спрашивается только один раз.Сценарий также принимает выходной файл в качестве аргумента и помещает в файл следующее:

Bob is at work.
Bob is feeling frustrated.

Теперь я пытаюсь расширить сценарий, чтобы я мог вводить переменные из командной строки (какесли бы я уже знал, о чем собирался спросить).Таким образом, команда будет выглядеть (в данном случае):

python script.py infile outfile Bob work frustrated

И она выдаст тот же результат.В идеале расширение должно запрашивать у пользователя оставшиеся переменные, если после команды, введенной в командной строке, осталось больше.Поэтому, если я запустлю скрипт как:

python script.py infile outfile Bob work

Сценарий все равно выдаст запрос:

Emotion?

Избыточные переменные в командной строке будут игнорироваться.Я довольно плохо знаком с Python, поэтому, хотя это кажется довольно простым, мне не удалось обновить мой текущий скрипт с помощью этого дополнения.Прикреплен скрипт:

import argparse
from os import path
import re

replacements = {}
pattern = '<<([^>]*)>>'

def user_replace(match):
    ## Pull from replacements dict or prompt
    placeholder = match.group(1)
    if placeholder in replacements:
        return replacements[placeholder]
    ## .setdefault(key, value) returns the value if present, else sets it then returns
    return replacements.setdefault(placeholder, raw_input('%s? ' % placeholder))

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('infile', type=argparse.FileType('r'))
    parser.add_argument('outfile', type=argparse.FileType('w'))
    args = parser.parse_args()

    matcher = re.compile(pattern)

    for line in args.infile:
        new_line = matcher.sub(user_replace, line)
        args.outfile.write(new_line)

    args.infile.close()
    args.outfile.close()

if __name__ == '__main__':
    main()

Редактировать: приведенный выше пример входного файла произвольный.В действительности входной файл может иметь любое количество переменных, повторяемых любое количество раз.

1 Ответ

3 голосов
/ 22 июля 2011

ОК, если вы хотите динамически генерировать параметры:

parser = argparse.ArgumentParser()
parser.add_argument('infile', type=argparse.FileType('r'))
parser.add_argument('outfile', type=argparse.FileType('w'))

required, extra = parser.parse_known_args()
infile, outfile = required.infile, required.outfile

args = re.findall(pattern, infile.read())
infile.seek(0)

parser = argparse.ArgumentParser()
for arg in args:
    parser.add_argument('--' + arg.lower())

replacements = vars(parser.parse_args(extra))

Это даст вам словарь всех аргументов.Каждое значение аргумента будет строкой внутри списка.Затем вы просто делаете

def user_replace(match):
    """Pull from replacements dict or prompt"""
    placeholder = match.group(1)
    return (replacements[placeholder][0] 
             if placeholder in replacements else 
              raw_input('%s? ' % placeholder))

Редактировать: я редактировал код вверху, чтобы установить аргументы.Таким образом, аргументы необязательны, и вы можете иметь любое число.Их имена по-прежнему будут name, location и emotion в replacements.

Теперь пользователь может делать:

python script.py infile outfile --name Bob --emotion 'extremely frustrated'

, опуская те из них, которые ему нужны, и заключая строки в кавычки.

Редактировать 2: отредактировановерхняя часть, поэтому он динамически получает аргументы из текстового файла.

...