2011-07-22 18 views
2

現在、私は以下のことをするスクリプトを持っています。私は行のテキストファイルがある場合:検索と置換のpythonスクリプトを拡張してコマンドラインから変数を受け入れる方法は?

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

編集:上記の入力ファイルの例は任意です。実際には、入力ファイルは任意の数の変数を持つことができ、任意の回数繰り返します。

答えて

3

OK、あなたは動的なオプションを生成したい場合:これはあなたのすべての引数の辞書を与える

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,locationemotionreplacementsになります。

ユーザーが行うことができます。

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

は、彼らがの入力を求めるプロンプトを表示するものを除外し、引用符で囲まれたスペースで文字列を囲みます。

編集2:上部を編集して、テキストファイルからargsを動的に取得します。

+0

最初のビットをループする方法はありますか。それで、任意の数の引数に対して機能するでしょうか?上記の名前、場所、感情のビットは単なる例でした。実際には、ユーザーにはもっと多くの引数があるかもしれません。 –

+0

私はあなたが何を望んでいるのか分からないが、推測で私の答えを更新した。 – agf

+0

私の考えは、入力ファイルに新しい行を追加するとします: <>は<になりました> それは次のようになりますので その後、同じスクリプトを使用して、私は、次の4つの引数を書くことができます:「ボブOUTFILEのpython script.pyのINFILEは挫折党の仕事」 出力は次のようになります。 「ボブは仕事です。 ボブは不満を感じています。 ボブは現在パーティーにいます。 –

関連する問題