Как извлечь подстроку между двумя маркерами?
Скажем, у меня есть строка 'gfgfdAAA1234ZZZuijjk'
, и я хочу извлечь только часть '1234'
.
Я знаю только, что будет за несколько символов непосредственно перед AAA
, а после ZZZ
- часть, которую меня интересует 1234
.
С sed
можно сделать что-то вроде этого со строкой:
echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"
И это даст мне 1234
.
Как сделать то же самое в Python?
Ответы
Ответ 1
Использование регулярных выражений - документация для дальнейшей справки
import re
text = 'gfgfdAAA1234ZZZuijjk'
m = re.search('AAA(.+?)ZZZ', text)
if m:
found = m.group(1)
# found: 1234
или
import re
text = 'gfgfdAAA1234ZZZuijjk'
try:
found = re.search('AAA(.+?)ZZZ', text).group(1)
except AttributeError:
# AAA, ZZZ not found in the original string
found = '' # apply your error handling
# found: 1234
Ответ 2
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> start = s.find('AAA') + 3
>>> end = s.find('ZZZ', start)
>>> s[start:end]
'1234'
Затем вы можете использовать регулярные выражения с модулем re, если хотите, но это не обязательно в вашем случае.
Ответ 3
регулярное выражение
import re
re.search(r"(?<=AAA).*?(?=ZZZ)", your_text).group(0)
Вышеуказанное as-is потерпит неудачу с AttributeError
, если в your_text
нет "AAA" и "ZZZ",
строковые методы
your_text.partition("AAA")[2].partition("ZZZ")[0]
Приведенное выше вернет пустую строку, если в your_text
не существует "AAA" или "ZZZ".
PS Python Challenge?
Ответ 4
import re
print re.search('AAA(.*?)ZZZ', 'gfgfdAAA1234ZZZuijjk').group(1)
Ответ 5
Вы можете сделать, используя только одну строку кода
>>> import re
>>> re.findall(r'\d{1,5}','gfgfdAAA1234ZZZuijjk')
>>> ['1234']
результат получит список...
Ответ 6
Вы можете использовать re для этого:
>>> import re
>>> re.compile(".*AAA(.*)ZZZ.*").match("gfgfdAAA1234ZZZuijjk").groups()
('1234,)
Ответ 7
Удивило, что никто не упомянул об этом, что является моей быстрой версией для одноразовых скриптов:
>>> x = 'gfgfdAAA1234ZZZuijjk'
>>> x.split('AAA')[1].split('ZZZ')[0]
'1234'
Ответ 8
С sed можно сделать что-то вроде этого со строкой:
echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"
И это даст мне 1234 в результате.
Вы можете сделать то же самое с функцией re.sub
, используя одно и то же регулярное выражение.
>>> re.sub(r'.*AAA(.*)ZZZ.*', r'\1', 'gfgfdAAA1234ZZZuijjk')
'1234'
В базовом sed группа захвата представлена \(..\)
, но в python она была представлена (..)
.
Ответ 9
Вы можете найти первую подстроку с этой функцией в вашем коде (по символьному индексу). Кроме того, вы можете найти, что есть после подстроки.
def FindSubString(strText, strSubString, Offset=None):
try:
Start = strText.find(strSubString)
if Start == -1:
return -1 # Not Found
else:
if Offset == None:
Result = strText[Start+len(strSubString):]
elif Offset == 0:
return Start
else:
AfterSubString = Start+len(strSubString)
Result = strText[AfterSubString:AfterSubString + int(Offset)]
return Result
except:
return -1
# Example:
Text = "Thanks for contributing an answer to Stack Overflow!"
subText = "to"
print("Start of first substring in a text:")
start = FindSubString(Text, subText, 0)
print(start); print("")
print("Exact substring in a text:")
print(Text[start:start+len(subText)]); print("")
print("What is after substring \"%s\"?" %(subText))
print(FindSubString(Text, subText))
# Your answer:
Text = "gfgfdAAA1234ZZZuijjk"
subText1 = "AAA"
subText2 = "ZZZ"
AfterText1 = FindSubString(Text, subText1, 0) + len(subText1)
BeforText2 = FindSubString(Text, subText2, 0)
print("\nYour answer:\n%s" %(Text[AfterText1:BeforText2]))
Ответ 10
В Python извлечение строки формы подстроки можно выполнить с findall
метода findall
в findall
регулярного выражения (re
).
>>> import re
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> ss = re.findall('AAA(.+)ZZZ', s)
>>> print ss
['1234']
Ответ 11
>>> s = '/tmp/10508.constantstring'
>>> s.split('/tmp/')[1].split('constantstring')[0].strip('.')
Ответ 12
На всякий случай кто-то должен будет сделать то же самое, что и я. Мне пришлось извлечь все в круглые скобки в строке. Например, если у меня есть такая линия, как "президент США (Барак Обама) встретился с...", и я хочу получить только "Барак Обаму", это решение:
regex = '.*\((.*?)\).*'
matches = re.search(regex, line)
line = matches.group(1) + '\n'
т.е. вам нужно заблокировать скобки с помощью знака slash \
. Хотя это проблема более регулярных выражений, которые Python.
Кроме того, в некоторых случаях вы можете увидеть символы 'r' перед определением regex. Если префикс r отсутствует, вам нужно использовать escape-символы, такие как C. Здесь больше обсуждать это.
Ответ 13
text = 'I want to find a string between two substrings'
left = 'find a '
right = 'between two'
print(text[text.index(left)+len(left):text.index(right)])
дает
string
Ответ 14
Здесь решение без регулярных выражений, которое также учитывает сценарии, в которых первая подстрока содержит вторую подстроку. Эта функция найдет подстроку, только если второй маркер находится после первого маркера.
def find_substring(string, start, end):
len_until_end_of_first_match = string.find(start) + len(start)
after_start = string[len_until_end_of_first_match:]
return string[string.find(start) + len(start):len_until_end_of_first_match + after_start.find(end)]
Ответ 15
Другой способ сделать это - использовать списки (предположим, что искомая подстрока состоит только из чисел):
string = 'gfgfdAAA1234ZZZuijjk'
numbersList = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
output = []
for char in string:
if char in numbersList: output.append(char)
print(f"output: {''.join(output)}")
### output: 1234
Ответ 16
Один лайнер, который возвращает другую строку, если не было совпадения. Редактировать: улучшенная версия использует next
функцию, замените "not-found"
чем-то другим, если необходимо:
import re
res = next( (m.group(1) for m in [re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk" ),] if m), "not-found" )
Мой другой способ сделать это, менее оптимальный, использует регулярное выражение во второй раз, но не нашел более короткого пути:
import re
res = ( ( re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk") or re.search("()","") ).group(1) )