Hoe de substring tussen twee markeringen extraheren?

Stel dat ik een string 'gfgfdAAA1234ZZZuijjk'heb en dat ik alleen het '1234'gedeelte wil extraheren.

Ik weet alleen wat de paar karakters zijn direct voor AAA, en na ZZZhet deel waarin ik geïnteresseerd ben 1234.

Met sedis het mogelijk om zoiets als dit te doen met een string:

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

En dit geeft me 1234als resultaat.

Hoe doe je hetzelfde in Python?


Antwoord 1, autoriteit 100%

Reguliere expressies gebruiken – documentatievoor verdere referentie

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

of:

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

Antwoord 2, autoriteit 18%

>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> start = s.find('AAA') + 3
>>> end = s.find('ZZZ', start)
>>> s[start:end]
'1234'

Dan kun je desgewenst ook regexps gebruiken met de re-module, maar dat is in jouw geval niet nodig.


Antwoord 3, autoriteit 13%

gewone uitdrukking

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

Het bovenstaande zoals het is zal mislukken met een AttributeErrorals er geen “AAA” en “ZZZ” in your_text

staan

string-methoden

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

Het bovenstaande retourneert een lege tekenreeks als “AAA” of “ZZZ” niet bestaan in your_text.

PS Python-uitdaging?


Antwoord 4, autoriteit 3%

Verbaasd dat niemand dit heeft genoemd, wat mijn snelle versie is voor eenmalige scripts:

>>> x = 'gfgfdAAA1234ZZZuijjk'
>>> x.split('AAA')[1].split('ZZZ')[0]
'1234'

Antwoord 5, autoriteit 2%

import re
print re.search('AAA(.*?)ZZZ', 'gfgfdAAA1234ZZZuijjk').group(1)

Antwoord 6, autoriteit 2%

u kunt doen met slechts één regel code

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

resultaat zal lijst ontvangen…


Antwoord 7

Je kunt daarvoor de module regebruiken:

>>> import re
>>> re.compile(".*AAA(.*)ZZZ.*").match("gfgfdAAA1234ZZZuijjk").groups()
('1234,)

Antwoord 8

Met sed is het mogelijk om zoiets als dit te doen met een string:

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

En dit geeft me 1234 als resultaat.

Je zou hetzelfde kunnen doen met de functie re.submet dezelfde regex.

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

In standaard sed wordt de capture-groep weergegeven door \(..\), maar in python werd deze weergegeven door (..).


Antwoord 9

In python kan het extraheren van een substring-vormstring worden gedaan met behulp van de findall-methode in de reguliere expressie (re) module.

>>> import re
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> ss = re.findall('AAA(.+)ZZZ', s)
>>> print ss
['1234']

Antwoord 10

>>> s = '/tmp/10508.constantstring'
>>> s.split('/tmp/')[1].split('constantstring')[0].strip('.')

Antwoord 11

Je vindt de eerste substring met deze functie in je code (op karakterindex). U kunt ook vinden wat er achter een subtekenreeks staat.

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]))

Antwoord 12

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)])

Geeft

string

Antwoord 13

Voor het geval iemand hetzelfde moet doen als ik. Ik moest alles tussen haakjes in een regel extraheren. Als ik bijvoorbeeld een regel heb als ‘Amerikaanse president (Barack Obama) ontmoette …’ en ik wil alleen ‘Barack Obama’, dan is dit de oplossing:

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

D.w.z. je moet haakjes blokkeren met het teken slash \. Hoewel het een probleem is met meer reguliere expressies dan Python.

Ook zie je in sommige gevallen ‘r’-symbolen vóór de definitie van Regex. Als er geen R-prefix is, moet u escape-tekens gebruiken zoals in C. hier is meer discussie over dat.


14

één voering met python 3.8:

text[text.find(start:='AAA')+len(start):text.find('ZZZ')]

15

Hier is een oplossing zonder regex die ook rekeningen voor scenario’s waar de eerste substring de tweede substring bevat. Deze functie vindt alleen een substring als de tweede marker na de eerste marker is.

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)]

16

Nog een manier om het te doen is lijsten gebruiken (veronderstellen van de substring die u zoekt, is alleen gemaakt van cijfers):

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

17

Typescript. Krijgt een string tussen twee andere snaren.

Zoekt de kortste reeks tussen voorvoegsels en postfixes

Voorvoegsels – String / Selectie van strings / null (betekent vanaf het begin zoeken).

Postfixes – String / Selectie van strings / null (betekent zoeken tot het einde).

public getStringInBetween(str: string, prefixes: string | string[] | null,
                          postfixes: string | string[] | null): string {
    if (typeof prefixes === 'string') {
        prefixes = [prefixes];
    }
    if (typeof postfixes === 'string') {
        postfixes = [postfixes];
    }
    if (!str || str.length < 1) {
        throw new Error(str + ' should contain ' + prefixes);
    }
    let start = prefixes === null ? { pos: 0, sub: '' } : this.indexOf(str, prefixes);
    const end = postfixes === null ? { pos: str.length, sub: '' } : this.indexOf(str, postfixes, start.pos + start.sub.length);
    let value = str.substring(start.pos + start.sub.length, end.pos);
    if (!value || value.length < 1) {
        throw new Error(str + ' should contain string in between ' + prefixes + ' and ' + postfixes);
    }
    while (true) {
        try {
            start = this.indexOf(value, prefixes);
        } catch (e) {
            break;
        }
        value = value.substring(start.pos + start.sub.length);
        if (!value || value.length < 1) {
            throw new Error(str + ' should contain string in between ' + prefixes + ' and ' + postfixes);
        }
    }
    return value;
}

18

één voeringen die een andere reeks terugkeren als er geen overeenkomst was.
EDIT: Verbeterde versie gebruikt nextfunctie, vervang "not-found"met iets anders indien nodig:

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

Mijn andere methode om dit te doen, minder optimaal, gebruikt regex 2nd time, maar vond nog steeds geen kortere manier:

import re
res = ( ( re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk") or re.search("()","") ).group(1) )

Other episodes