¿Cómo extraer la subcadena entre dos marcadores?

Digamos que tengo una cadena 'gfgfdAAA1234ZZZuijjk' y quiero extraer solo la parte '1234' .

Solo sé cuáles serán los pocos caracteres directamente antes de AAA , y después de ZZZ la parte que me interesa es 1234 .

Con sed es posible hacer algo como esto con una cuerda:

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

Y esto me dará 1234 como resultado.

¿Cómo hacer lo mismo en Python?

Uso de expresiones regulares – documentación para futuras referencias

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

o:

 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 
 >>> s = 'gfgfdAAA1234ZZZuijjk' >>> start = s.find('AAA') + 3 >>> end = s.find('ZZZ', start) >>> s[start:end] '1234' 

Luego puede usar expresiones regulares con el módulo re también, si lo desea, pero eso no es necesario en su caso.

expresión regular

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

Tal como está, fallará con un AttributeError si no hay "AAA" y "ZZZ" en su your_text

métodos de cadena

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

Lo anterior devolverá una cadena vacía si "AAA" o "ZZZ" no existen en your_text .

PS Python Challenge?

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

Puedes usar re modulo para eso:

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

Con sed es posible hacer algo como esto con una cuerda:

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

Y esto me dará 1234 como resultado.

Podría hacer lo mismo con la función re.sub usando la misma expresión regular.

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

En sed básico, el grupo de captura está representado por \(..\) , pero en python fue representado por (..) .

Puedes hacerlo usando solo una línea de código

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

el resultado recibirá la lista …

Puede encontrar la primera subcadena con esta función en su código (por índice de caracteres). Además, puedes encontrar lo que está después de una subcadena.

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

En Python, la cadena de formulario de extracción de subcadenas se puede hacer usando el método findall en el módulo ( re ) de expresiones regulares.

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

Solo en caso de que alguien tenga que hacer lo mismo que yo hice. Tuve que extraer todo entre paréntesis en una línea. Por ejemplo, si tengo una línea como “El presidente de EE. UU. (Barack Obama) se reunió con …” y quiero obtener solo “Barack Obama”, esta es la solución:

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

Es decir, necesita bloquear paréntesis con slash \ signo. Aunque es un problema sobre expresiones más regulares que Python.

Además, en algunos casos puede ver los símbolos ‘r’ antes de la definición de expresiones regulares. Si no hay un prefijo r, necesita usar caracteres de escape como en C. Aquí hay más discusión sobre eso.

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

Sorprendido de que nadie haya mencionado esto, que es mi versión rápida para scripts únicos:

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

Aquí hay una solución sin expresiones regulares que también da cuenta de los escenarios donde la primera subcadena contiene la segunda subcadena. Esta función solo encontrará una subcadena si el segundo marcador está después del primer marcador.

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

Da

 string 

Un forro que devuelve otra cadena si no hubo coincidencia. Edición: la versión mejorada usa la next función, reemplaza "not-found" con otra cosa si es necesario:

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

Mi otro método para hacer esto, menos óptimo, usa expresiones regulares por segunda vez, todavía no encontré una forma más corta:

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