Как получить все символы до числа? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть строки, подобные приведенным ниже

>>> s1
'this_is-a.string-123-with.number'
>>> s2
'this_is-a123.456string-123-with.number'
>>> s3
'one-0more-str.999'

необходимо получить все до всех чисел (не alphanumeri c) после разделения, поэтому получите this_is-a.string- из s1 и this_is-a123.456string- из s2 и one-0more-str. из s3.

>>> for a in re.split('-|_|\.',s2):
...    if a.isdigit():
...       r=re.split(a,s2)[0]
...       break
>>> print(r)
# expected: this_is-a123.456string-
# got: this_is-a

Приведенный выше фрагмент кода работает для s1, но не для s2, так как 123 соответствует a123 в s2, должен быть лучший способ pythoni c ?

Дополнительная информация:

с примером s3, когда мы разделяем с - или _ или . в качестве разделителя, 999 - единственное, что мы получаем как все числа Таким образом, все, что до этого, было one-0more-str., которое должно быть напечатано, если мы возьмем s2 в качестве примера, после разделения с помощью da sh или подчеркивания или точки в качестве разделителя, 123 будет all number (isdi git), поэтому получите все до того, что this_is-a123.456string-, поэтому, если входная строка будет this_1s-a-4.test, выходной будет this_1s-a-, потому что 4 - это число после разделения.

Ответы [ 4 ]

1 голос
/ 23 апреля 2020

Это будет работать для ваших примеров:

def fn(s):
    return re.match("(.*?[-_.]|^)\d+([-_.]|$)", s).group(1)

(^ и $ соответствуют началу и концу строки соответственно, а ? в .*? делает не жадное совпадение.)

Еще несколько случаев:

>>> fn("111")
""

>>> fn(".111")
"."

>>> fn(".1.11")
"."

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

>>> fn("foobar")
0 голосов
/ 24 апреля 2020

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

import re
s1='this_is-a.string-123-with.number'
s2='this_is-a123.456string-123-with.number'
s3='one-0more-str.999'

# matches any group that is in between "all numbers"...
regex = re.compile('(.*[-\._])\d+([-\._].*)?')  

m = regex.match(s1)
print(m.groups())

m = regex.match(s2)
print(m.groups())

m = regex.match(s3)
print(m.groups())

, когда вы запустите это, результат будет следующим:

('this_is-a.string-', '-with.number')
('this_is-a123.456string-', '-with.number')
('one-0more-str.', None)

Если вас интересует только первая группа, вы можете использовать только:

>>> print(m.group(1))
one-0more-str.

Если вы хотите отфильтровать случаи, когда второй группы нет:

>>> print([i for i in m.groups() if i])
['one-0more-str.']
0 голосов
/ 24 апреля 2020

Это работает для вас примеры

Код

def parse(s):
  """ Splits on successive digits, 
      then takes everything up to last split on digits """
  return ''.join(re.split(r'(\d+)', s)[:-2])

Тесты

Использование указанных строк

for t in ['this_is-a.string-123-with.number',
          'this_is-a123.456string-123-with.number',
          'one-0more-str.999']:
    print(f'{parse(t)}')

Вывод

this_is-a.string-
this_is-a123.456string-
one-0more-str.

Пояснение

Строка

s = 'this_is-a123.456string-123-with.number'

Разделить на группу цифр

re.split(r'(\d+)', s)
Out: ['this_is-a', '123', '.', '456', 'string-', '123', '-with.number']

Оставить последние два элемента в разбиении

re.split(r'(\d+)', s)[:-2] # [:-2] slice dropping last two items of list
Out: ['this_is-a', '123', '.', '456', 'string-']

Объединить список в строку

''.join(re.split(r'(\d+)', s)[:-2]) # join items
Out: this_is-a123.456string-
0 голосов
/ 23 апреля 2020

Не уверен, что это будет работать во всех случаях, но вы можете попробовать:

for a in re.split('-|_|\.',s2).reverse():
    if a.isdigit():
        r=re.rsplit(a,s2)[0]
        break
print(r)
...