Передача метасимволов в Python в качестве аргументов из командной строки - PullRequest
9 голосов
/ 22 апреля 2011

Я делаю программу на Python, которая будет анализировать поля в некоторых строках ввода. Я бы хотел, чтобы пользователь вводил разделитель полей в качестве опции из командной строки. Я использую optparse, чтобы сделать это. Я сталкиваюсь с проблемой, что ввод что-то вроде \t будет разделяться буквально на \t, а не на вкладке, что я и хочу. Я почти уверен, что это Python, а не оболочка, так как я попробовал все комбо цитат, обратной косой черты и t, которые я могу придумать.

Если бы я мог получить optparse, чтобы аргумент был простым вводом (есть ли такая вещь?), А не raw_input, я думаю, это сработало бы. Но я понятия не имею, как это сделать.

Я также пробовал различные подстановки и приемы регулярных выражений, чтобы превратить строку из двух символов "\t" во вкладку из одного символа, но безуспешно.

Пример, где input.txt:

field 1[tab]field\t2

(Примечание: [tab] - это символ табуляции, а field\t2 - строка из 8 символов)

parseme.py:

#!/usr/bin/python
from optparse import OptionParser  
parser = OptionParser()  
parser.add_option("-d", "--delimiter", action="store", type="string",  
    dest="delimiter", default='\t')  
parser.add_option("-f", dest="filename")  
(options, args) = parser.parse_args()  
Infile = open(options.filename, 'r')  
Line = Infile.readline()  

Fields = Line.split(options.delimiter)  
print Fields[0]  
print options.delimiter  

Infile.close()  

Это дает мне:

$ parseme.py -f input.txt  
field 1  
[tab]

Эй, отлично, настройки по умолчанию работали правильно. (Да, я знаю, что мог бы просто установить \ t по умолчанию и забыть об этом, но я хотел бы знать, как справиться с этим типом проблемы.)

$ parseme.py -f input.txt -d '\t'  
field 1[tab]field  
\t

Это не то, что я хочу.

Ответы [ 4 ]

7 голосов
/ 22 апреля 2011
>>> r'\t\n\v\r'.decode('string-escape')
'\t\n\x0b\r'
0 голосов
/ 22 апреля 2011

Опция callback - хороший способ справиться с непростыми делами:

parser.add_option("-d", "--delimiter", action="callback", type="string",
                  callback=my_callback, default='\t')

с соответствующей функцией (определяется до парсера, затем):

def my_callback(option, opt, value, parser):
    val = value
    if value == '\\t':
        val = '\t'
    elif value == '\\n':
        val = '\n'
    parser.values.delimiter = val

Вы можете проверить это работает через командную строку: python test.py -f test.txt -d \t (без кавычек вокруг \t, они бесполезны).

Преимущество заключается в обработке опции через модуль 'optparse', а не через последующую обработку результатов анализа.

0 голосов
/ 22 апреля 2011

решая это из вашего скрипта:

options.delimiter = re.sub("\\\\t","\t",options.delimiter)

вы можете адаптировать его для соответствия более экранированным символам (\ n, \ r и т. Д.)

еще один способ решения проблемы вне питона:

когда вы вызываете свой скрипт из оболочки, сделайте это так:

parseme.py -f input.txt -d '^V<tab>'

^ V означает «нажать Ctrl + V»

затем нажмите обычную клавишу табуляции

это правильно передаст символ табуляции вашему скрипту Python;

0 голосов
/ 22 апреля 2011

Быстрый и грязный способ состоит в том, чтобы eval это, вот так:

eval(options.delimiter, {}. {})

Дополнительные пустые символы предназначены для предотвращения случайного слипания вашей программы.

...