Python 如何提取两个标记之间的子字符串?

Python 如何提取两个标记之间的子字符串?,python,string,substring,Python,String,Substring,假设我有一个字符串'gfgfdaaa1234zzzuijk',我只想提取'1234'部分 我只知道我感兴趣的部分1234前面和后面的几个字符是什么 使用sed可以使用字符串执行以下操作: echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|" 这将给我带来1234 如何在Python中执行相同的操作 >>> s = 'gfgfdAAA1234ZZZuijjk' >>> start = s.find('AAA') +

假设我有一个字符串
'gfgfdaaa1234zzzuijk'
,我只想提取
'1234'
部分

我只知道我感兴趣的部分
1234
前面和后面的几个字符是什么

使用
sed
可以使用字符串执行以下操作:

echo "$STRING" | sed -e "s|.*AAA\(.*\)ZZZ.*|\1|"
这将给我带来
1234

如何在Python中执行相同的操作

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

然后,您也可以将regexps与re模块一起使用,如果您愿意的话,但在您的情况下这不是必需的

使用正则表达式-供进一步参考

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

text = 'gfgfdAAA1234ZZZuijjk'

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

# found: 1234
或:

您可以使用该模块:

>>> import re
>>> re.compile(".*AAA(.*)ZZZ.*").match("gfgfdAAA1234ZZZuijjk").groups()
('1234,)
正则表达式 如果
您的_文本中不存在“AAA”或“ZZZ”,则上述内容将返回空字符串


PS Python挑战?

以防万一,有人会像我一样做同样的事情。我必须把括号里的所有东西都提取出来。例如,如果我有一句像“美国总统(巴拉克·奥巴马)会见……”这样的话,我只想得到“巴拉克·奥巴马”,这就是解决方案:

regex = '.*\((.*?)\).*'
matches = re.search(regex, line)
line = matches.group(1) + '\n'
也就是说,您需要用
斜杠\
符号来阻止括号。尽管这是一个关于Python中更多正则表达式的问题

此外,在某些情况下,您可能会在正则表达式定义之前看到“r”符号。若并没有r前缀,你们需要使用像C中的转义字符。关于这一点还有更多的讨论

>>> s = '/tmp/10508.constantstring'
>>> s.split('/tmp/')[1].split('constantstring')[0].strip('.')
使用sed,可以使用字符串执行以下操作:

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

这个结果会给我1234

您可以使用相同的正则表达式对
re.sub
函数执行相同的操作

>>> re.sub(r'.*AAA(.*)ZZZ.*', r'\1', 'gfgfdAAA1234ZZZuijjk')
'1234'
在基本sed中,捕获组由
\(..)
表示,但在python中它由
(..)
表示

您可以在代码中找到使用此函数的第一个子字符串(按字符索引)。此外,您还可以找到子字符串后面的内容


如果没有匹配项,则返回另一个字符串的一行程序。 编辑:改进版使用
下一步
功能,如果需要,用其他内容替换
“未找到”

import re
res = next( (m.group(1) for m in [re.search("AAA(.*?)ZZZ", "gfgfdAAA1234ZZZuijjk" ),] if m), "not-found" )
我的另一种方法,不太理想,第二次使用regex,仍然没有找到一种更短的方法:

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

您只需使用一行代码即可完成

>>> import re

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

>>> ['1234']

在python中,可以使用正则表达式(
re
)模块中的
findall
方法提取子字符串形式字符串


令人惊讶的是,没有人提到这是我的一次性脚本快速版本:

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

这里有一个不带正则表达式的解决方案,它还考虑了第一个子字符串包含第二个子字符串的情况。仅当第二个标记位于第一个标记之后时,此函数才会查找子字符串

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


另一种方法是使用列表(假设您要查找的子字符串仅由数字组成):

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

使用PyParsing

将pyparsing导入为pp
word=pp.word(pp.alphanums)
s='GFGFDAAA1234ZZUIJK'
规则=pp.nestedExpr('AAA','ZZZ')
对于规则中的匹配。搜索字符串:
打印(匹配)
这将产生:

[['1234']]

打字稿。获取其他两个字符串之间的字符串

在前缀和后缀之间搜索最短字符串

前缀-字符串/字符串数组/null(表示从开始搜索)

postfix-字符串/字符串数组/null(表示搜索到结尾)

公共getStringInBetween(str:string,前缀:string | string[]| null, 后缀:string | string[]| null):string{ 如果(前缀类型==='string'){ 前缀=[前缀]; } if(后缀的类型=='string'){ 后缀=[后缀]; } 如果(!str | | str.length<1){ 抛出新错误(str+'应包含'+前缀); } 让start=前缀===null?{pos:0,sub:'}:this.indexOf(str,前缀); const end=postfix==null?{pos:str.length,sub:''}:this.indexOf(str,postfix,start.pos+start.sub.length); let value=str.substring(start.pos+start.sub.length,end.pos); 如果(!value | | value.length<1){ 抛出新错误(str+'应该包含'+前缀+'和'+后缀'之间的字符串); } while(true){ 试一试{ start=this.indexOf(值、前缀); }捕获(e){ 打破 } value=value.substring(start.pos+start.sub.length); 如果(!value | | value.length<1){ 抛出新错误(str+'应该包含'+前缀+'和'+后缀'之间的字符串); } } 返回值; }
AttributeError:“非类型”对象没有属性“组”
-如果字符串中没有AAA、ZZZ…这个问题似乎暗示输入文本将始终包含“AAA”和“ZZZ”。如果不是这样的话,你的答案会失败得很惨(我的意思是它返回了完全错误的东西,而不是一个空字符串或抛出一个异常;把“hello there”当作输入字符串)。@user225312是
re
方法,但速度不是更快吗?Voteup,但是我会使用“x='AAA';s.find(x)+len x”而不是“s.find('AAA')+3”用于可维护性。如果在
s
中找不到任何令牌,
s.find
将返回
-1
。切片操作符
s[begin:end]
将接受它作为有效索引,并返回不需要的子字符串。@confused00 find比re快得多。如果模式大部分时间匹配,则第二种解决方案更好,因为它的索引不是从0开始的吗?所以您需要使用组(0)而不是组(1)?@Alexander,否,组(0)将返回完全匹配的字符串:AAA1234ZZZ,组(1)将只返回与第一个组匹配的字符:1234@Bengt:为什么?第一个解决方案在我看来相当简单
>>> import re
>>> s = 'gfgfdAAA1234ZZZuijjk'
>>> ss = re.findall('AAA(.+)ZZZ', s)
>>> print ss
['1234']
>>> x = 'gfgfdAAA1234ZZZuijjk'
>>> x.split('AAA')[1].split('ZZZ')[0]
'1234'
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)])
string
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
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;
}