сохранять блоки в кавычках при разбиении по разделителю - PullRequest
0 голосов
/ 20 ноября 2018

В качестве примера приведена строка s = 'Hi, my name is Humpty-Dumpty, from "Alice, Through the Looking Glass"', и я хочу разделить ее на следующие фрагменты:

# To Do: something like {l = s.split(',')}
l = ['Hi', 'my name is Humpty-Dumpty', '"Alice, Through the Looking Glass"']

Я не знаю, где и сколько разделителей я найду.

Это моя первоначальная идея, и она довольно длинная и не точная, поскольку она удаляет все разделители, в то время как я хочу, чтобы разделители внутри кавычек сохранялись:

s = 'Hi, my name is Humpty-Dumpty, from "Alice, Through the Looking Glass"'
ss = []
inner_string = ""
delimiter = ','

for item in s.split(delimiter):
    if not inner_string: 
        if '\"' not in item: # regullar string. not intersting
            ss.append(item)
        else:
            inner_string += item # start inner string

    elif inner_string:
        inner_string += item

        if '\"' in item:  # end inner string
            ss.append(inner_string)
            inner_string = ""
        else:            # middle of inner string
            pass

print(ss)
# prints ['Hi', ' my name is Humpty-Dumpty', ' from "Alice Through the Looking Glass"'] which is OK-ish

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Я решил эту проблему, полностью исключив split:

s = 'Hi, my name is Humpty-Dumpty, from "Alice, Through the Looking Glass"'
l = []
substr = ""
quotes_open = False

for c in s:
    if c == ',' and not quotes_open: # check for comma only if no quotes open
        l.append(substr)
        substr = ""
    elif c == '\"':
        quotes_open = not quotes_open
    else:
        substr += c

l.append(substr)

print(l)

Вывод:

['Hi', ' my name is Humpty-Dumpty', ' from Alice, Through the Looking Glass']

Более обобщенная функция может выглядеть примерно так:

def custom_split(input_str, delimiter=' ', avoid_between_char='\"'):
    l = []
    substr = ""
    between_avoid_chars = False
    for c in s:
        if c == delimiter and not between_avoid_chars:
            l.append(substr)
            substr = ""
        elif c == avoid_between_char:
            between_avoid_chars = not between_avoid_chars
        else:
            substr += c
    l.append(substr)
    return l
0 голосов
/ 20 ноября 2018

Вы можете разделить по регулярным выражениям с помощью re.split:

>>> import re
>>> [x for x in re.split(r'([^",]*(?:"[^"]*"[^",]*)*)', s) if x not in (',','')]

, когда s равно:

'Hi, my name is Humpty-Dumpty, from "Alice, Through the Looking Glass"'

это выводит:

['Hi', ' my name is Humpty-Dumpty', ' from "Alice, Through the Looking Glass"']

Объяснение регулярного выражения:

(
    [^",]*          zero or more chars other than " or ,
    (?:             non-capturing group
        "[^"]*"     quoted block
        [^",]*      followed by zero or more chars other than " or ,
    )*              zero or more times
)
0 голосов
/ 20 ноября 2018

это будет работать для этого конкретного случая и может обеспечить отправную точку.

import re
s = 'Hi, my name is Humpty-Dumpty, from "Alice, Through the Looking Glass"'

cut = re.search('(".*")', s)

r = re.sub('(".*")', '$VAR$', s).split(',')
res = []
for i in r:
    res.append(re.sub('\$VAR\$', cut.group(1), i))

Вывод

print(res)
['Hi', ' my name is Humpty-Dumpty', ' from "Alice, Through the Looking Glass"']
...