2015-07-19 26 views
2

您好我是Python和RegEx的新手。我正在尝试使用这两种方法,试图获得一个正则表达式来从用户提取数据,但我期望不同的输入考虑错别字等。因此,在下面的代码中,我随机选择了一些类型的字符串,我希望用户给你举个例子他们如何输入数据。我只对美元之前或之后的数字感兴趣。例如:字符和数字的多个字符串的有效正则表达式

ran = random.randint(1, 7) 
print str(ran) 
if ran == 1: 
    examplestring = "This item costs 20 USD contact 9999999" 
elif ran == 2: 
    examplestring = "This item costs USD 20" 
elif ran == 3: 
    examplestring = "This item costs 20 U.S.D" 
elif ran == 4: 
    examplestring = "This item costs 20 usd" 
elif ran == 5: 
    examplestring = "This item costs 20 Usd call to buy : 954545577" 
elif ran == 6: 
    examplestring = "This item costs 20USD" 
elif ran == 7: 
    examplestring = "This item costs usd20" 

regex = re.compile(r'\busd|\bu.s.d\b|\bu.s.d.\b', re.I) 
examplestring = regex.sub("USD", examplestring) 
costs = re.findall(r'\d+.\bUSD\b|\bUSD\b.\d+|\d+USD\b|\bUSD\d+', examplestring) 
cost = "".join(str(n) for n in costs[0]) 
cost = ''.join(x for x in cost if x.isdigit()) 
print cost + " USD" 

使用这些正则表达式我可以得到我想要的是“20美元”的细节。我的问题是,如果我以正确的方式进行,并且能够使代码更好?

+0

你可以做到这一切与一个正则表达式:'(:(<= USD | USD)\ S *(\ d +)?)|(?:\ d + \ s *(?= USD | usd | Usd | USD))'但是由于正则表达式的复杂性,有时这不是一个好的方法。请参阅[此处](https://regex101.com/r/mH0cC8/1)有关它的工作原理的解释。 – RedX

回答

1

一个办法做到这一点:

regex = re.compile(r'\b(?=[0-9U])(?:[0-9]+\s*U\.?S\.?D|U\.?S\.?D\s*[0-9]+)\b', re.I) 

result = [x.strip(' USD.usd') for x in regex.findall(yourstring)] 

图案的详细资料:

\b   # word boundary 
(?=[0-9U]) # only here to quickly discard word-boundaries not followed 
      # by a digit or the letter U without to test the two branches 
      # of the following alternation. You can remove it if you want. 

(?: 
    [0-9]+\s*U\.?S\.?D # USD after 
    |     # OR 
    U\.?S\.?D\s*[0-9]+ # USD before 
) 
\b 

注意,空格和圆点是可选的两个分支。

然后结果的“USD”部分用一个简单的条删除。它比试图将美元从比赛结果中排除在外并且更方便(可能更快)。

+0

这很好,非常感谢你,但如果用户犯了一个错字,并给出类似于u,s,d而不是u.s.d的内容,我该如何包含这些逗号呢? –

+0

@Cheth_K:不可能处理宇宙中所有可能的拼写错误,但对于您的具体问题,请用'[,。]'替换'\ .',并在条带字符列表中添加逗号。 –

+0

太棒了非常感谢你! –

0

作为一个非常通用的解决方案,[0-9]+只会提取数量,忽略其他围绕它的文本。它着重于你需要提取什么,而不是可能忽略什么。

+0

好的,我编辑它,我第一次没有正确发布它。用户还可以提供其他输入,如电话号码。所以我认为我需要的数字总是来自紧接在usd之后或之前。 –

+0

为什么downvote?在我回答之前,OP改变了规格,然后我的回答是有效的。 – user1016274

+0

我不知道谁低估了它,没有我 –

0

你可以使用一组正则表达式直接提取值。例如“(\ d +)* u \。?s \。?d \。?| u \。s \。?d \。?*(\ d +)”可用于搜索您的字符串忽略指定的情况),然后,如果您匹配,则您的费用将位于组1或组2中,具体取决于匹配的变体。

1

我建议Regex101了解更多信息并解释给定的正则表达式。特别是你应该注意组(如(\d+)),因为我认为这是你需要正确提取一个值。

替换,然后搜索这个替换字符串在某种程度上是凌乱的我认为。

import re 
lines = """This item costs 20 USD 
This item costs USD 20 
This item costs 20 U.S.D 
This item costs 20 usd 
This item costs 20 Usd 
This item costs 20USD 
This item costs usd20""" 

# as you can see there are two groups with the price 
pattern = re.compile(r"u\.?s\.?d\s*(\d+)|(\d+)\s*u\.?s\.?d", re.I) 
# one of the groups must have matched, so I take the non-empty one using `or`operator 
print ["{} USD".format(fst or sec) for fst, sec in pattern.findall(lines)] 

日期:

['20 USD', '20 USD', '20 USD', '20 USD', '20 USD', '20 USD', '20 USD'] 
+0

使用逻辑测试是一个非常好的主意。 –

相关问题