сопоставлять двойные кавычки с двойными кавычками внутри - PullRequest
2 голосов
/ 02 апреля 2012

У меня есть строка Python:

string = '"/dev/null" "" "19/1333329478.9381399" 0 1 "cam-foo" 64 900.0 "Foo x rev scan of test" "/usr/bin/env ""PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"" python app.py" 60.145855 2.034689'

Мне нужно регулярное выражение, которое дает мне список всех элементов в этой строке.Элемент: любое число или любая строка в двойных кавычках.Строка может содержать двойные кавычки.

Я выступил с этим регулярным выражением:

import re    
p = re.compile(r'"[^"]*"|[-\.\d]+')
p.findall(string)
['"/dev/null"', '""', '"19/1333329478.9381399"', '0', '1', '"cam-foo"', '64', '900.0', '"Foo x rev scan of test"', '"/usr/bin/env "', '"PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"', '" python app.py"', '60.145855', '2.034689']

Как вы можете видеть, я пропускаю часть двойных кавычек внутри строки. Двойную кавычку внутри элемента следует игнорировать. Мне бы хотелось получить такой результат:

['"/dev/null"', '""', '"19/1333329478.9381399"', '0', '1', '"cam-foo"', '64', '900.0', '"Foo x rev scan of test"', '"/usr/bin/env ""PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"" python app.py"', '60.145855', '2.034689']

Вместо 3 (или более) элементов

[..., '"/usr/bin/env "', '"PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"', '" python app.py"', ...]

Мне бы хотелось иметь только один элемент:

'"/usr/bin/env ""PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"" python app.py"'

Кто-нибудь может мне помочь?

Ответы [ 4 ]

3 голосов
/ 02 апреля 2012

Вы можете использовать csv модуль .

Пример

>>> import csv
>>> from pprint import pprint
>>> pprint(list(csv.reader([string], delimiter=' ', quotechar='"')))
[
[
'/dev/null'
,
''
,
'19/1333329478.9381399'
,
'0'
,
'1'
,
'cam-foo'
,
'64'
,
'900.0'
,
'Foo x rev scan of test'
,
'/usr/bin/env "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH" python app.py'
,
'60.145855'
,
'2.034689'
]
]
2 голосов
/ 02 апреля 2012

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

r'"[^"]*"'

Вы можете достичь желаемого результата, изменив строки, внутри которых вы соответствуетеокружающие двойные кавычки.

r'"(?:[^"]|"")*"'

Это регулярное выражение соответствует паре двойных кавычек, которые окружают ноль или более строк;каждая строка должна состоять из одного символа без двойных кавычек или двух последовательных двойных кавычек.(?: помечает заключенный в скобки бит как не захватывающую группу; в противном случае Python вернет бит только в скобках.)

Давайте подключим это к вашему полному регулярному выражению:

% python
Python 2.7.2 (default, Mar 20 2012, 13:27:18) 
[GCC 4.2.1 Compatible Apple Clang 3.1 (tags/Apple/clang-318.0.54)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import re
>>> s = '"/dev/null" "" "19/1333329478.9381399" 0 1 "cam-foo" 64 900.0 "Foo x rev scan of test" "/usr/bin/env ""PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"" python app.py" 60.145855 2.034689'
>>> for el in re.findall(r'"(?:[^"]|"")*"|[-\.\d]+', s): print(el)
... 
"/dev/null"
""
"19/1333329478.9381399"
0
1
"cam-foo"
64
900.0
"Foo x rev scan of test"
"/usr/bin/env ""PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"" python app.py"
60.145855
2.034689
>>>
1 голос
/ 02 апреля 2012

Если все, что вам нужно, это иметь возможность разбить этот точный случай, вы можете использовать shlex.split():

>>> import shlex
>>> s = '"/dev/null" "" "19/1333329478.9381399" 0 1 "cam-foo" 64 900.0 "Foo x rev scan of test" "/usr/bin/env ""PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH"" python app.py" 60.145855 2.034689'
>>> shlex.split(s)
['/dev/null', '', '19/1333329478.9381399', '0', '1', 'cam-foo', '64', '900.0', 'Foo x rev scan of test', '/usr/bin/env PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH python app.py', '60.145855', '2.034689']
>>> shlex.split(s)[-3]
'/usr/bin/env PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:$PATH python app.py'

Это не регулярное выражение, но оно будет решать эту проблему для вас каждый раз.

0 голосов
/ 02 апреля 2012

Заключите поисковый токен в ().Что происходит, вы не получите и не вернете список для каждой находки.Выберите правильный элемент массива.Например:

m = p.findall(string)

Возвращает список в m, каждый элемент которого снова является списочным токеном в соответствии с тем, что было включено в your ().Таким образом, вы можете получить ту часть утверждения, которую вы хотите.

...