Jak wyodrębnić podłańcuch między dwoma znacznikami?

Załóżmy, że mam Ciąg 'gfgfdAAA1234ZZZuijjk' i chcę wyodrębnić tylko '1234' część.

Wiem tylko, co będzie kilka znaków bezpośrednio przed AAA, a po ZZZ część, która mnie interesuje 1234.

Z sed można zrobić coś takiego za pomocą ciągu znaków:

echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"

I to da mi 1234 w rezultacie.

Jak zrobić to samo w Pythonie?

Author: Aran-Fey, 2011-01-12

12 answers

Używanie wyrażeń regularnych- Dokumentacja dla dalszego odniesienia

import re

text = 'gfgfdAAA1234ZZZuijjk'

m = re.search('AAA(.+?)ZZZ', text)
if m:
    found = m.group(1)

# found: 1234

Lub:

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
 364
Author: eumiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-08 15:50:59
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> start = s.find('AAA') + 3
>>> end = s.find('ZZZ', start)
>>> s[start:end]
'1234'

Następnie możesz używać wyrażeń regularnych z modułem re, jeśli chcesz, ale nie jest to konieczne w Twoim przypadku.

 82
Author: Lennart Regebro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 09:17:23

Wyrażenie regularne

import re

re.search(r"(?<=AAA).*?(?=ZZZ)", your_text).group(0)

Powyższe as-is zawiedzie z AttributeError jeśli nie ma "AAA" i "ZZZ" w your_text

Metody łańcuchowe

your_text.partition("AAA")[2].partition("ZZZ")[0]

Powyższe zwróci pusty łańcuch, jeśli" AAA " lub " ZZZ " nie istnieją w your_text.

PS Python Challenge?

 31
Author: tzot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-06 23:43:17
import re
print re.search('AAA(.*?)ZZZ', 'gfgfdAAA1234ZZZuijjk').group(1)
 13
Author: infrared,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 09:18:00

Możesz użyć Re moduł do tego:

>>> import re
>>> re.compile(".*AAA(.*)ZZZ.*").match("gfgfdAAA1234ZZZuijjk").groups()
('1234,)
 6
Author: andreypopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-12 09:19:21

Z sed można zrobić coś takiego za pomocą łańcucha:

echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"

To da mi 1234.

Możesz zrobić to samo z re.sub funkcją używając tego samego wyrażenia regularnego.

>>> re.sub(r'.*AAA(.*)ZZZ.*', r'\1', 'gfgfdAAA1234ZZZuijjk')
'1234'

W podstawowym sed Grupa przechwytywania jest reprezentowana przez \(..\), ale w Pythonie była reprezentowana przez (..).

 5
Author: Avinash Raj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-31 08:29:21

Możesz znaleźć pierwszy podłańcuch z tą funkcją w kodzie (według indeksu znaków). Ponadto, można znaleźć to, co jest po podłańcuchu.

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]))
 4
Author: Saeed Zahedian Abroodi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-21 05:38:35

Na wypadek, gdyby ktoś musiał zrobić to samo, co ja. Musiałem wyodrębnić wszystko wewnątrz nawiasu w linii. Na przykład, jeśli mam linię jak " prezydent USA (Barack Obama) spotkał się z ... a ja chcę dostać tylko 'Baracka Obamę' to jest rozwiązanie:

regex = '.*\((.*?)\).*'
matches = re.search(regex, line)
line = matches.group(1) + '\n'

Czyli musisz zablokować nawias za pomocą znaku slash \. Chociaż jest to problem o więcej wyrażeń regularnych, że Python.

Ponadto, w niektórych przypadkach możesz zobaczyć symbole 'r' przed definicją regex. Jeśli nie ma r prefiks, musisz użyć znaków escape, jak w C. Tutaj jest więcej dyskusji na ten temat.

 2
Author: wzbozon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:07

Możesz to zrobić używając tylko jednej linijki kodu

>>> import re

>>> re.findall(r'\d{1,5}','gfgfdAAA1234ZZZuijjk')

>>> ['1234']

Wynik otrzyma listę...

 2
Author: mahesh gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-11 11:39:55
>>> s = '/tmp/10508.constantstring'
>>> s.split('/tmp/')[1].split('constantstring')[0].strip('.')
 1
Author: user1810100,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-11 09:23:44

W Pythonie, ekstrakcję fragmentu łańcucha można wykonać metodą findall w module wyrażenia regularnego (re).

>>> import re
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> ss = re.findall('AAA(.+)ZZZ', s)
>>> print ss
['1234']
 0
Author: rashok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 09:11:23

Jeden Liner, który zwraca inny łańcuch, jeśli nie było dopasowania. Edit: ulepszona wersja używa funkcji next, w razie potrzeby zastąp "not-found" czymś innym:

import re
res = next( (m.group(1) for m in [re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk" ),] if m), "not-found" )

Moja inna metoda aby to zrobić, mniej optymalna, używa regex 2nd time, nadal nie znalazłem krótszego sposobu:

import re
res = ( ( re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk") or re.search("()","") ).group(1) )
 0
Author: MaxLZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 18:31:44