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 AAA, y después ZZZ de la parte que me interesa 1234.

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

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

Y esto me dará 1234 como resultado.

Cómo hacer lo mismo en Python?

Author: Aran-Fey, 2011-01-12

12 answers

Usando expresiones regulares - documentación para mayor referencia

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
 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-08 15:50:59
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> start = s.find('AAA') + 3
>>> end = s.find('ZZZ', start)
>>> s[start:end]
'1234'

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

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-12 09:17:23

Expresión regular

import re

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

El as-is anterior fallará con un AttributeError si no hay " AAA "y" ZZZ " en 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?

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-12 09:18:00

Puedes usar el módulo re para eso:

>>> 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-12 09:19:21

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

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

Y esto me dará 1234 como resultado.

Podrías 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 estaba representado por (..).

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-31 08:29:21

Puede encontrar la primera subcadena con esta función en su código (por índice de caracteres). Además, puede 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]))
 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-21 05:38:35

Por si acaso alguien tendrá que hacer lo mismo que yo. Tuve que extraer todo dentro de paréntesis en una línea. Por ejemplo, si tengo una línea como 'presidente de estados unidos (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, debe bloquear el paréntesis con el signo slash \. Aunque es un problema sobre expresiones más regulares que Python.

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

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:07

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

>>> import re

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

>>> ['1234']

El resultado recibirá la lista...

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-11 09:23:44

En python, la extracción de una cadena de forma de subcadena se puede hacer usando el método findall en el módulo de expresión regular (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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-14 09:11:23

Una línea que devuelve otra cadena si no hay coincidencia. Editar: la versión mejorada usa la función next, reemplaza "not-found" con algo más 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, utiliza regex 2nd tiempo, todavía no encontró una manera más corta:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-03 18:31:44