Znajdź łańcuch pomiędzy dwoma podłańcuchami [duplikat]

To pytanie ma już odpowiedź tutaj:

Jak znaleźć łańcuch pomiędzy dwoma podłańcuchami ('123STRINGabc' -> 'STRING')?

Moja obecna metoda wygląda tak:

>>> start = 'asdf=5;'
>>> end = '123jasd'
>>> s = 'asdf=5;iwantthis123jasd'
>>> print((s.split(start))[1].split(end)[0])
iwantthis
Wydaje się to jednak bardzo nieefektywne i nie-pythoniczne. Jaki jest lepszy sposób na coś takiego to?

Zapomniałem wspomnieć: Łańcuch może nie zaczynać się i nie kończyć na start i end. Mogą mieć więcej znaków przed i po.

Author: John Howard, 2010-07-30

20 answers

import re

s = 'asdf=5;iwantthis123jasd'
result = re.search('asdf=5;(.*)123jasd', s)
print result.group(1)
 187
Author: Nikolaus Gradwohl,
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
2010-07-30 05:59:57
s = "123123STRINGabcabc"

def find_between( s, first, last ):
    try:
        start = s.index( first ) + len( first )
        end = s.index( last, start )
        return s[start:end]
    except ValueError:
        return ""

def find_between_r( s, first, last ):
    try:
        start = s.rindex( first ) + len( first )
        end = s.rindex( last, start )
        return s[start:end]
    except ValueError:
        return ""


print find_between( s, "123", "abc" )
print find_between_r( s, "123", "abc" )

Daje:

123STRING
STRINGabc

Pomyślałem, że należy to zauważyć - w zależności od tego, jakiego zachowania potrzebujesz, możesz mieszać index i rindex wywołania lub przejść z jedną z powyższych wersji (jest to odpowiednik grup regex (.*) i (.*?)).

 140
Author: cji,
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
2010-07-30 06:27:01
s[len(start):-len(end)]
 42
Author: Tim McNamara,
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
2010-07-30 05:56:47
start = 'asdf=5;'
end = '123jasd'
s = 'asdf=5;iwantthis123jasd'
print s[s.find(start)+len(start):s.rfind(end)]

Daje

iwantthis
 41
Author: ansetou,
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-01-03 12:29:39

Formatowanie łańcuchów dodaje pewną elastyczność temu, co zasugerował Nikolaus Gradwohl. start i end mogą być teraz zmieniane zgodnie z życzeniem.

import re

s = 'asdf=5;iwantthis123jasd'
start = 'asdf=5;'
end = '123jasd'

result = re.search('%s(.*)%s' % (start, end), s).group(1)
print(result)
 30
Author: Tim McNamara,
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-08-27 14:31:52

Wystarczy zamienić własne rozwiązanie OP na odpowiedź:

def find_between(s, start, end):
  return (s.split(start))[1].split(end)[0]
 11
Author: reubano,
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-11-10 12:10:16

Oto jeden sposób, aby to zrobić

_,_,rest = s.partition(start)
result,_,_ = rest.partition(end)
print result

Inny sposób za pomocą wyrażenia regularnego

import re
print re.findall(re.escape(start)+"(.*)"+re.escape(end),s)[0]

Lub

print re.search(re.escape(start)+"(.*)"+re.escape(end),s).group(1)
 10
Author: John La Rooy,
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
2010-07-30 06:03:29
source='your token _here0@df and maybe _here1@df or maybe _here2@df'
start_sep='_'
end_sep='@df'
result=[]
tmp=source.split(start_sep)
for par in tmp:
  if end_sep in par:
    result.append(par.split(end_sep)[0])

print result

Musi pokazać: TU0, TU1, TU2

Regex jest lepszy, ale będzie wymagał dodatkowej lib an możesz chcieć przejść tylko dla Pythona

 8
Author: tstoev,
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-09-24 11:23:28

Aby wyodrębnić STRING, spróbuj:

myString = '123STRINGabc'
startString = '123'
endString = 'abc'

mySubString=myString[myString.find(startString)+len(startString):myString.find(endString)]
 3
Author: Wikis,
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-04-24 09:21:35

Moją metodą będzie zrobienie czegoś takiego,

find index of start string in s => i
find index of end string in s => j

substring = substring(i+len(start) to j-1)
 2
Author: joshu,
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
2010-07-30 06:20:22

To w zasadzie odpowiedź cji-30 Lip '10 o 17: 58. Zmieniłem strukturę try except dla trochę większej jasności co spowodowało wyjątek.

def find_between( inputStr, firstSubstr, lastSubstr ):
'''
find between firstSubstr and lastSubstr in inputStr  STARTING FROM THE LEFT
    http://stackoverflow.com/questions/3368969/find-string-between-two-substrings
        above also has a func that does this FROM THE RIGHT   
'''
start, end = (-1,-1)
try:
    start = inputStr.index( firstSubstr ) + len( firstSubstr )
except ValueError:
    print '    ValueError: ',
    print "firstSubstr=%s  -  "%( firstSubstr ), 
    print sys.exc_info()[1]

try:
    end = inputStr.index( lastSubstr, start )       
except ValueError:
    print '    ValueError: ',
    print "lastSubstr=%s  -  "%( lastSubstr ), 
    print sys.exc_info()[1]

return inputStr[start:end]    
 2
Author: Love and peace - Joe Codeswell,
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-10 20:01:16

Te rozwiązania zakładają, że ciąg początkowy i końcowy są różne. Oto rozwiązanie, którego używam dla całego pliku, gdy wskaźniki początkowe i końcowe są takie same, zakładając, że cały plik jest odczytywany za pomocą readlines ():

def extractstring(line,flag='$'):
    if flag in line: # $ is the flag
        dex1=line.index(flag)
        subline=line[dex1+1:-1] #leave out flag (+1) to end of line
        dex2=subline.index(flag)
        string=subline[0:dex2].strip() #does not include last flag, strip whitespace
    return(string)

Przykład:

lines=['asdf 1qr3 qtqay 45q at $A NEWT?$ asdfa afeasd',
    'afafoaltat $I GOT BETTER!$ derpity derp derp']
for line in lines:
    string=extractstring(line,flag='$')
    print(string)

Daje:

A NEWT?
I GOT BETTER!
 2
Author: Wesley Kitlasten,
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
2016-05-19 18:51:28

Możesz po prostu użyć tego kodu lub skopiować poniższą funkcję. Wszystko starannie w jednej linii.

def substring(whole, sub1, sub2):
    return whole[whole.index(sub1) : whole.index(sub2)]

Jeśli uruchomisz funkcję w następujący sposób.

print(substring("5+(5*2)+2", "(", "("))

Pobably zostanie z wyjściem:

(5*2

Zamiast

5*2

Jeśli chcesz mieć ciągi podrzędne na końcu wyjścia, kod musi wyglądać jak poniżej.

return whole[whole.index(sub1) : whole.index(sub2) + 1]

Ale jeśli nie chcesz, aby podciągi były na końcu, to +1 musi być na pierwszej wartości.

return whole[whole.index(sub1) + 1 : whole.index(sub2)]
 2
Author: thecollinsprogram,
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-01-15 10:28:53

Oto funkcja, którą zrobiłem, aby zwrócić listę z szukanym łańcuchem(łańcuchami) inbetween string1 i string2.

def GetListOfSubstrings(stringSubject,string1,string2):
    MyList = []
    intstart=0
    strlength=len(stringSubject)
    continueloop = 1

    while(intstart < strlength and continueloop == 1):
        intindex1=stringSubject.find(string1,intstart)
        if(intindex1 != -1): #The substring was found, lets proceed
            intindex1 = intindex1+len(string1)
            intindex2 = stringSubject.find(string2,intindex1)
            if(intindex2 != -1):
                subsequence=stringSubject[intindex1:intindex2]
                MyList.append(subsequence)
                intstart=intindex2+len(string2)
            else:
                continueloop=0
        else:
            continueloop=0
    return MyList


#Usage Example
mystring="s123y123o123pp123y6"
List = GetListOfSubstrings(mystring,"1","y68")
for x in range(0, len(List)):
               print(List[x])
output:


mystring="s123y123o123pp123y6"
List = GetListOfSubstrings(mystring,"1","3")
for x in range(0, len(List)):
              print(List[x])
output:
    2
    2
    2
    2

mystring="s123y123o123pp123y6"
List = GetListOfSubstrings(mystring,"1","y")
for x in range(0, len(List)):
               print(List[x])
output:
23
23o123pp123
 2
Author: Mnyikka,
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-19 08:37:03

To zamieściłem wcześniej jako fragment kodu w Daniweb :

# picking up piece of string between separators
# function using partition, like partition, but drops the separators
def between(left,right,s):
    before,_,a = s.partition(left)
    a,_,after = a.partition(right)
    return before,a,after

s = "bla bla blaa <a>data</a> lsdjfasdjöf (important notice) 'Daniweb forum' tcha tcha tchaa"
print between('<a>','</a>',s)
print between('(',')',s)
print between("'","'",s)

""" Output:
('bla bla blaa ', 'data', " lsdjfasdj\xc3\xb6f (important notice) 'Daniweb forum' tcha tcha tchaa")
('bla bla blaa <a>data</a> lsdjfasdj\xc3\xb6f ', 'important notice', " 'Daniweb forum' tcha tcha tchaa")
('bla bla blaa <a>data</a> lsdjfasdj\xc3\xb6f (important notice) ', 'Daniweb forum', ' tcha tcha tchaa')
"""
 1
Author: Tony Veijalainen,
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
2010-07-30 07:16:36
from timeit import timeit
from re import search, DOTALL


def partition_find(string, start, end):
    return string.partition(start)[2].rpartition(end)[0]


def re_find(string, start, end):
    # applying re.escape to start and end would be safer
    return search(start + '(.*)' + end, string, DOTALL).group(1)


def index_find(string, start, end):
    return string[string.find(start) + len(start):string.rfind(end)]


# The wikitext of "Alan Turing law" article form English Wikipeida
# https://en.wikipedia.org/w/index.php?title=Alan_Turing_law&action=edit&oldid=763725886
string = """..."""
start = '==Proposals=='
end = '==Rival bills=='

assert index_find(string, start, end) \
       == partition_find(string, start, end) \
       == re_find(string, start, end)

print('index_find', timeit(
    'index_find(string, start, end)',
    globals=globals(),
    number=100_000,
))

print('partition_find', timeit(
    'partition_find(string, start, end)',
    globals=globals(),
    number=100_000,
))

print('re_find', timeit(
    're_find(string, start, end)',
    globals=globals(),
    number=100_000,
))

Wynik:

index_find 0.35047444528454114
partition_find 0.5327825636197754
re_find 7.552149639286381

re_find był prawie 20 razy wolniejszy niż index_find w tym przykładzie.

 1
Author: AXO,
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-02-05 05:59:11

Parsowanie tekstu za pomocą ograniczników z różnych platform poczty e-mail stanowiło większą wersję tego problemu. Zazwyczaj mają początek i koniec. Znaki ogranicznika dla symboli wieloznacznych utrzymywały regex dławienia. Problem ze Splitem jest wymieniony tutaj i gdzie indziej-oops, znak ogranicznika zniknął. Przyszło mi do głowy, aby użyć replace (), aby dać split() coś innego do konsumpcji. Fragment kodu:

nuke = '~~~'
start = '|*'
stop = '*|'
julien = (textIn.replace(start,nuke + start).replace(stop,stop + nuke).split(nuke))
keep = [chunk for chunk in julien if start in chunk and stop in chunk]
logging.info('keep: %s',keep)
 1
Author: Matthew Dunn,
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-05 00:39:20

Jeśli nie chcesz niczego importować, spróbuj użyć metody string .index():

text = 'I want to find a string between two substrings'
left = 'find a '
right = 'between two'

# Output: 'string'
print text[text.index(left)+len(left):text.index(right)]
 1
Author: user3423639,
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-07-23 21:02:12

Dalej od odpowiedzi Nikolaus Gradwohl, musiałem uzyskać numer wersji (tj., 0.0.2) between ('ui: 'and' -') from below file content (filename: docker-compose.yml):

    version: '3.1'
services:
  ui:
    image: repo-pkg.dev.io:21/website/ui:0.0.2-QA1
    #network_mode: host
    ports:
      - 443:9999
    ulimits:
      nofile:test

I tak to u mnie działało (skrypt Pythona):

import re, sys

f = open('docker-compose.yml', 'r')
lines = f.read()
result = re.search('ui:(.*)-', lines)
print result.group(1)


Result:
0.0.2
 0
Author: Akshay,
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-04-18 09:34:18

To wydaje mi się dużo prostsze:

import re

s = 'asdf=5;iwantthis123jasd'
x= re.search('iwantthis',s)
print(s[x.start():x.end()])
 -4
Author: Chris Martin,
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-04-11 02:53:41