使用正则表达式匹配直到遇到“-”后跟字母为止?

4
我有多个带有连字符的字符串,如果连字符后面跟着字母而不是数字,我只想获取连字符之前的表达式。
我已经使用了:
re.search("^([^-])+","3x130-140k-ZZ-ABC") 

但它返回的是3x130,这只包含第一个破折号之前的内容。我想要3x130-140k,因为只有第二个破折号后面跟着字母。

我需要一个正则表达式,从3x130-140k-ZZ-ABC 中返回3x130-140k,并从3x140k-ZZ-ABC 中返回3x140k


我指的是任何字母,无论大小写。重点是该字母紧跟在破折号后面。 - ranemak
两个问题:(1)通过“破折号后跟字母”,您是指紧随破折号的整个单词(直到下一个破折号)应由字母组成,还是指直接在破折号后面的下一个字符应该是一个字母? (2)如果字符串中没有符合条件的破折号,您想要返回什么? 什么都不返回,一个空字符串还是整个字符串? - Stef
答案:(1) 只是下一个字符 (2) 整个字符串 - ranemak
4个回答

0
你可以使用 -[a-zA-Z] 来匹配一个破折号和一个字母。然后,你可以取出这个匹配之前的字符串部分:
import re
raw_string = "3x130-140k-ZZ-ABC"
match = re.search("-[a-zA-z]", raw_string)
print(raw_string[:match.start()])

输出:

3x130-140k

看起来不错,但有时字符串中也可能会有特殊字符。 - ranemak

0

你也可以在第一个连字符后面跟着一个字符[a-zA-Z]上使用split,并将maxsplit限制为1。

import re

strings = [
    "3x130-140k-ZZ-ABC",
    "3x140k-ZZ-ABC"
]
pattern = r"-[a-zA-Z]"
for s in strings:
    print(re.split(pattern, s, 1)[0])

输出

3x130-140k
3x140k

@ranemak 您好,欢迎您。请注意,从15个声望点数开始,您将有可能为所有被证明有帮助的答案投票支持。 - The fourth bird

0

您可以使用

^.*?(?=-[A-Za-z])

请查看正则表达式演示详情:

  • ^ - 字符串的开头
  • .*? - 任何零个或多个字符,除了换行符之外,尽可能少
  • (?=-[A-Za-z]) - 紧接着-和ASCII字母的位置(使用(?=-[^\W\d_])匹配任何Unicode字母)。

请查看Python演示:

import re
text = "3x130-140k-ZZ-ABC"
m = re.search(r"^.*?(?=-[A-Za-z])", text)
if m:
    print(m.group()) # => 3x130-140k

@ranemak 非常好,需要注意的是像[^-]*这样的否定字符类在这里无法使用,因为您需要匹配任何不跟随字母的-,但是作为一种相当高效的构造方式,它是很好记住的。不过,^([^-]*(?:-(?![A-Za-z])[^-]*)*)-[A-Za-z] 也可能可以使用。 - Wiktor Stribiżew

0
不需要正则表达式。使用 str.split(txt, '-') 在破折号上进行分割,然后使用 next 找到第一个破折号后面跟着一个满足 word.isalpha() 的单词的索引。
def eat_until_dash_alphaword(txt, dash='-'):
    words = txt.split(dash)
    i = next((i for i in range(1, len(words)+1) if words[i].isalpha()), None)  # whole word is alpha
    #i = next((i for i in range(1, len(words)+1) if words[i][0].isalpha()), None)  # first char is alpha
    if i is not None:
        return dash.join(words[:i])
    else:
        return txt # or raise an error, or return empty string

print(eat_until_dash_alphaword("3x130-140k-ZZ-ABC"))
# 3x130-140k

如果你想找到第一个破折号后面至少一个字母字符,那么它甚至更简单。你根本不需要使用str.split,只需要对字符进行简单的迭代即可:
from itertools import pairwise

def eat_until_dash_alphachar(txt, dash='-'):
    for i, (a, b) in enumerate(pairwise(txt)):
        if a == dash and b.isalpha():
            return txt[:i]
    return txt # or raise an error, or return empty string

print(eat_until_dash_alphachar("3x130-140k-ZZ-ABC"))
# 3x130-140k

相比之前的答案,这个问题相当复杂,但还是感谢你的努力! - ranemak
@ranemak 这只是个人口味问题。我个人认为这样更简单。它会迭代字符,直到找到一对字符 a, b,其中 a'-'b 是字母。条件 if a == dash and b.isalpha(): 相当明确。 - Stef

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接