Разделите заданную строку с помощью регулярного выражения

#python #regex

#python #регулярное выражение

Вопрос:

Пытаюсь разбить строку на 2 части.

 #Need to get 'I1234' and 'I56/I78'
name1 = 'I1234/I56/I78'

#Need to get 'I1234 ' and 'I56/I78'
name2 = 'I1234 /I56/I78'      

#Need to get 'I1234 ' and 'I56 /I78'
name3 = 'I1234 /I56 /I78'

#Need to get '1234 ' and 'I56 /I78 '
name4 = 'I1234 /I56 /I78 '
  

Я попробовал это, и это сработало:

 pat_a = re.compile(r'(. )(/)(. )')

Is there a better way ?

result = re.findall(pat_a, name2[::-1])
  

Редактировать

Возможны более сложные строки, например:

 I78_[0]/abcd_/efg_ /I1234/I56
  

Комментарии:

1. Есть ли причина для отрицательного голосования?

2. Я не голосовал против, но, возможно, потому, что ваше описание не слишком четкое. «Пытаюсь разбить строку на 2 части». это мало что говорит нам о том, где в строке вы пытаетесь разорвать, или о шаблоне, который вы пытаетесь установить.

3. Как правильно разделить для I78_ [0]/abcd_ / efg_ /I1234 / I56 ?

4. @Dragonfly какой требуется вывод для более сложной строки? У меня было это в моем ответе — [‘ I78_[0]’, ‘abcd_ / efg_ / I1234 / I56’] — но правильно ли это?

Ответ №1:

Не уверен, что это лучше, но вы можете использовать partition or split с значением maxsplit=1, чтобы избежать re импорта модуля:

 print('I1234/I56/I78'.partition("/"))   # ('I1234', '/', 'I56/I78')

print('I1234/I56/I78'.split("/",1))     # ['I1234', 'I56/I78']
  

Для partition вам нужно было бы посмотреть на 0-й и 2-й индексы кортежа:

 first, _ , last = 'I1234/I56/I78'.partition("/")
  

Doku:


Полный пример:

 name1 = 'I1234/I56/I78' 
name2 = 'I1234 /I56/I78'       
name3 = 'I1234 /I56 /I78' 
name4 = 'I1234 /I56 /I78 '

for n in [name1,name2,name3,name4]:
    print(n.partition("/"))   # ('I1234', '/', 'I56/I78')
    print(n.split("/",1))     # ['I1234', 'I56/I78']
  

Вывод (обратные косые черты экранированы — вот почему они удваиваются):

 ('I1234', '/', 'I56/I78')           # using partition
['I1234', 'I56/I78']                # using split

('\I1234 ', '/', 'I56/I78')        # partition
['\I1234 ', 'I56/I78']             # split .. etc.

('\I1234 ', '/', '\I56 /I78')
['\I1234 ', '\I56 /I78']

('\I1234 ', '/', '\I56 /\I78 ')
['\I1234 ', '\I56 /\I78 ']
  

Комментарии:

1. Спасибо, Патрик, у меня есть еще несколько примеров. Я отредактировал свой вопрос.

2. Я дал вам преимущество, но я бы предложил разделить ваши два решения и показать их отдельно. Кроме того, я бы взял 1-й и 3-й компоненты результата ‘partition’ и распечатал их, чтобы вы показали, как получить желаемый результат в каждом случае. Как бы то ни было, ваш ответ немного сбивает с толку. — Мне нравится, что вы показываете две альтернативы.

3. @Steve — вот почему я разделил решения сверху , а также показал, как top разделил их с помощью декомпозиции. Спасибо за отзыв

4. @PatrickArtner — да, ничего особенного. Я просто думаю, что было бы понятнее иметь возможность просматривать как код, так и выходные данные в виде двух уникальных примеров.

5. Спасибо. Это решение работает для первых 4 строк, но не для более сложной строки.

Ответ №2:

В этом ответе используется string.split , который, по-видимому, является самым чистым методом по сравнению с регулярным выражением. Я рассматривал использование string.partition , но оно выдает tuple , что требует разделения индекса. Кроме того, выходные данные, связанные с string.partition , не выдают запрошенный вами вывод.

В этом первом примере берется одна строка и выводится пара строк на основе вашего запроса на разделение.

 # Need to get 'I1234 ' and 'I56 /I78'
name3 = 'I1234 /I56 /I78'

# The input name (name3) can be change in a for loop linked to your input. 
split_input = name3.split('/', 1) # maxsplit=1
print (split_input)
# outputs 
#####################################################################
# NOTE: the escaped backslashes, which doesn't match your requirement. 
#####################################################################
['\I1234 ', '\I56 /I78'] 
  

В исходном выводе выше были созданы экранированные обратные косые черты, поэтому этот код удаляет их.

 # Need to get 'I1234 ' and 'I56 /I78'
name3 = 'I1234 /I56 /I78'

# The input name (name3) can be change in a for loop linked to your input. 
split_input = str(name3.split('/', 1)).encode('utf-8').decode('unicode_escape')
print (split_input)
# outputs 
['I1234 ', 'I56 /I78'] # Do you need that trailing space?
  

Я не уверен, откуда изначально берутся ваши входные значения (например, файл, веб-сайт и т.д.), Поэтому я добавил значения из вашего вопроса в список для более быстрого тестирования. В следующем примере используются понимание списка и string.split.

 my_strings = ['I1234/I56/I78', 'I1234 /I56/I78', 'I1234 /I56 /I78', 'I1234 /I56 /I78', 'I78_[0]/abcd_/efg_ /I1234/I56']

# Uses list comprehension and string.split to split the elements in your strings
split_input = [x.split('/', 1) for x in my_strings]

# The original output created escaped backslashes, so this code removes them.
decode_output = (str(split_input).encode('utf-8').decode('unicode_escape'))

print (decode_output)
# outputs 
[['I1234', 'I56/I78'], ['I1234 ', 'I56/I78'], ['I1234 ', 'I56 /I78'], ['I1234 ', 'I56 /I78'], ['I78_[0]', 'abcd_/efg_ /I1234/I56']]
  

Комментарии:

1. Почему вы начинаете с совершенно другого ввода? Вместо строк вы используете списки списков строк, которые уже разделены. Также зачем эти махинации с экранированными обратными косыми чертами и разделением str() представления для вашего split_input ? Это ответ на совершенно другой вопрос…

2. Просмотрев мой ответ, я отметил, что опубликовал выходные данные кода в качестве входных значений. Я исправил эту ошибку. Спасибо, что указали на ошибку.

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