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 ZZZ
het deel waarin ik geïnteresseerd ben 1234
.
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.
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 AttributeError
als 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.sub
met 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 next
functie, 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) )