2015-07-19 24 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

使用邏輯測試是一個非常好的主意。 –

相關問題