Python RE(一句话,检查第一个字母是否区分大小写,其余字母是否区分大小写)
在下面的情况下,我想匹配字符串“Singapore”,其中“S”应该始终是大写,其余的单词可能是小写或大写。但在下面的文本中,字符串“s”是小写的,它在搜索条件中匹配。有谁能告诉我如何实施这一点Python RE(一句话,检查第一个字母是否区分大小写,其余字母是否区分大小写),python,regex,Python,Regex,在下面的情况下,我想匹配字符串“Singapore”,其中“S”应该始终是大写,其余的单词可能是小写或大写。但在下面的文本中,字符串“s”是小写的,它在搜索条件中匹配。有谁能告诉我如何实施这一点 import re st = "Information in sinGapore " if re.search("S""(?i)(ingapore)" , st): print "matched
import re
st = "Information in sinGapore "
if re.search("S""(?i)(ingapore)" , st):
print "matched"
Singapore => matched
sIngapore => notmatched
SinGapore => matched
SINGAPORE => matched
正如所评论的,丑陋的方式是:
>>> re.search("S[iI][Nn][Gg][Aa][Pp][Oo][Rr][Ee]" , "SingaPore")
<_sre.SRE_Match object at 0x10cea84a8>
>>> re.search("S[iI][Nn][Gg][Aa][Pp][Oo][Rr][Ee]" , "Information in sinGapore")
更新
根据您的评论-您可以使用:
reg.search(s).group().startswith("S")
而不是:
reg.search(s).group()[0]==("S")
如果它看起来更可读。您可以编写一个简单的lambda来生成难看但又完全重复的解决方案:
>>> leading_cap_re = lambda s: s[0].upper() + ''.join('[%s%s]' %
(c.upper(),c.lower())
for c in s[1:])
>>> leading_cap_re("Singapore")
'S[Ii][Nn][Gg][Aa][Pp][Oo][Rr][Ee]'
对于多字城市,请定义字符串拆分版本:
>>> leading_caps_re = lambda s : r'\s+'.join(map(leading_cap_re,s.split()))
>>> print leading_caps_re('Kuala Lumpur')
K[Uu][Aa][Ll][Aa]\s+L[Uu][Mm][Pp][Uu][Rr]
那么您的代码可能就是:
if re.search(leading_caps_re("Singapore") , st):
...etc...
而RE的丑陋纯粹是内部的。有趣的是
/((S)((?i)ingapore))/
在perl中做正确的事情,但在python中似乎不能按需要工作。为了公平起见,python文档清楚地说明了这一点,(?i)修改了整个regexp,因为您想要根据捕获短语(我知道,唯一名称或几个名称之间是空格分隔的)设置GV代码,所以必须有一个步骤,在字典中根据捕获短语选择代码。
因此,很容易从这一步中获利,对短语中的第一个字母(必须大写)或第一个名字进行测试,而没有正则表达式能够做到这一点 我选择了某些条件来构成测试。例如,名字中的点不是强制性的,但大写字母是强制性的。这些条件在需要时很容易改变 编辑1 编辑2 我改进了代码。它更简短,可读性更强。
指令
assert(……])
用于验证字典的键是否格式正确
import re
def doot(x):
return '\.?'.join(ch for ch in x) + '\.?'
def regexize(labels,doot=doot,
wg2 = '(%s) *( %s)',wnog2 = '(%s)(%s)',
ri = re.compile('(.(?!.*? )|[^ ]+)( ?) *(.+\Z)')):
to_join = []
modlabs = {}
for K in labels.iterkeys():
g1,g2,g3 = ri.match(K).groups()
to_join.append((wg2 if g2 else wnog2)
% (doot(g1), doot(g3.lower())))
modlabs[g1+g2+g3.lower()] = labels[K]
return (re.compile('|'.join(to_join), re.I), modlabs)
def code(X,labels,regexize = regexize):
reglab,modlabs = regexize(labels)
for ma in reglab.finditer(X):
a,b = tuple(x for x in ma.groups() if x)
k = (a + b.lower()).replace('.','')
GV = modlabs[k] if k in modlabs else '- bad match -'
yield ' {!s:15} {!s:^13}'.format(a+b, GV)
countries = {'Singapore':'SG','Austria':'AU',
'Swiss':'CH','Chile':'CL',
'Den LMM':'DN','LMM Den':'LM'}
assert(all('.' not in k and
(k.count(' ')==1 or k[0].upper()==k[0])
for k in countries))
s = (' Singapore SIngapore SiNgapore SinGapore'
' SI.Ngapore SIngaPore SinGaporE SinGAPore'
' SINGaporE SiNg.aPoR singapore sIngapore'
' siNgapore sinGapore sINgap.ore sIngaPore'
' sinGaporE sinGAPore sINGaporE siNgaPoRe'
' Austria Aus.trIA aUSTria AUSTRiA'
' Den L.M.M Den Lm.M DEn Lm.M.'
' DEN L.MM De.n L.M.M. Den LmM'
' L.MM DEn LMM DeN LM.m Den')
print '\n'.join(res for res in code(s,countries))
这是最好的答案:
(?-i:S)(?i)ingapore
作为证明:“S”应该始终是大写。@wooble——不,它应该是
S[iI][nN][gG][aA][pP][oO][rR][eE]
,但这太难看了……必须有更好的方法……呃,对。读取失败。@wooble它不满足所有条件。在“S”之后可能有大写字母@eyquem你能在这方面帮我吗?谢谢你的回复。有没有其他方法来写同样的内容?因为如果我有一个长字符串,那么整个字符串的编写可能会有问题。我认为reg.search(s)和reg.search(s.group()[0]=='S'
条件是可读的。@AdamMatan我认为你是对的-匹配所有较低的,然后仔细检查第一个字母是我能想到的Python的re的最好方法。…@Adam Matan感谢你的回答。我如何使用if-else循环实现相同的功能。例如,如果它匹配singapore,我想将全局vaiable GV设置为SG elif匹配australia将GV设置为AU等等…你没有错,但是正则表达式太难看且不可读。有更好的方法编写正则表达式,并支持其功能。@NHAHDH-我不是建议OP使用由开头的大写字母
创建的文字字符串,而是在内部使用难看的re字符串,如中所示我的编辑。我删除了我的否决票,因为我误解了re
中“flag”组的工作原理。它在整个表达式中的应用方式使得它几乎毫无用处。它工作得很好。但是在上面的“Singapore”中,我想看到“S”是大写字母和“ingapore”可以是小写字母或大写字母,也可以两者兼有。但上面的情况只适用于“Singapore”。我知道在perl中,我们使用regex,比如“S”“(?i)ingapore”.输出应为新加坡SG新加坡SG新加坡SG新加坡SG新加坡新加坡SG新加坡-不匹配-新加坡-不匹配-以及项目的结果和案例。“M”、“LMM DeN”等。对于“DeN Lm.M”这个案例,“DeN”应该是区分大小写的,“Lm.N”可能在任何一个案例中。对于“LMM DeN”这个案例,“LMM”应该区分大小写,“De”可能在任何一个案例中,“N”也应该区分大小写。什么!!?对于“LMM DeN”LMM
必须区分大小写(没关系,我的代码就是这样做的)而De
在任何情况下都是可以接受的,但是N
应该区分大小写?!为什么?事实上,我不需要知道为什么,我需要知道一般规则,而不是一个接一个地添加规则,否则过程将是永久的。请完全澄清规则。
import re
def doot(x):
return '\.?'.join(ch for ch in x) + '\.?'
def regexize(labels,doot=doot,
wg2 = '(%s) *( %s)',wnog2 = '(%s)(%s)',
ri = re.compile('(.(?!.*? )|[^ ]+)( ?) *(.+\Z)')):
to_join = []
modlabs = {}
for K in labels.iterkeys():
g1,g2,g3 = ri.match(K).groups()
to_join.append((wg2 if g2 else wnog2)
% (doot(g1), doot(g3.lower())))
modlabs[g1+g2+g3.lower()] = labels[K]
return (re.compile('|'.join(to_join), re.I), modlabs)
def code(X,labels,regexize = regexize):
reglab,modlabs = regexize(labels)
for ma in reglab.finditer(X):
a,b = tuple(x for x in ma.groups() if x)
k = (a + b.lower()).replace('.','')
GV = modlabs[k] if k in modlabs else '- bad match -'
yield ' {!s:15} {!s:^13}'.format(a+b, GV)
countries = {'Singapore':'SG','Austria':'AU',
'Swiss':'CH','Chile':'CL',
'Den LMM':'DN','LMM Den':'LM'}
assert(all('.' not in k and
(k.count(' ')==1 or k[0].upper()==k[0])
for k in countries))
s = (' Singapore SIngapore SiNgapore SinGapore'
' SI.Ngapore SIngaPore SinGaporE SinGAPore'
' SINGaporE SiNg.aPoR singapore sIngapore'
' siNgapore sinGapore sINgap.ore sIngaPore'
' sinGaporE sinGAPore sINGaporE siNgaPoRe'
' Austria Aus.trIA aUSTria AUSTRiA'
' Den L.M.M Den Lm.M DEn Lm.M.'
' DEN L.MM De.n L.M.M. Den LmM'
' L.MM DEn LMM DeN LM.m Den')
print '\n'.join(res for res in code(s,countries))
(?-i:S)(?i)ingapore