2016-06-08 27 views
3

我正在寫一個python程序來解析txt文件中的一些用戶數據。 文本文件中的一行將包含用戶的高度。 我已經指定了一個爲了用戶有望跟隨像re.sub python收集高度

文件應包含名稱,下一行,出生日期, 3號線,高度等

的第一行我也賜給一個示例文件看起來像這樣

名用戶:姓名
出生日期:2000年4月16日
年齡:16
身高:5英尺9英寸

當我讀取文件時,我看着每一行,並使用':'作爲分隔符來分割它。

第一個字段是我的專欄名稱,例如name,dob,age,height。

在某些情況下,用戶忘記了 ':' 姓名或出生日期之後,或者他們會簡單地發送數據,如:

  • 身高:5英尺9英寸
  • 5英尺9寸
  • 5英尺9在
  • 5英尺9英寸

我已經決定要使用的邏輯是:

  1. 在每一行上尋找':';如果找到了,那麼我有我的領域。
  2. 否則,請嘗試找出可能的數據。

爲高度的邏輯是這樣的:

if any(heightword in file_line.upper() for heightword in ['FT', 'HEIGHT', 'FEET', 'INCH', 'CM']) 

if條件將查找具有高度相關聯的話。

一旦我確定文件中的行包含高度,我希望能夠在將信息寫入數據庫之前將該信息轉換爲英寸。

請有人幫助我解決如何將以下數據轉換爲英寸。

  • 身高:5英尺9英寸
  • 5英尺9寸
  • 5英尺9
  • 5英尺9英寸

我知道,因爲我想,以滿足各種用戶輸入。這份清單並非詳盡無遺;我試圖用這些作爲例子來理解,然後我會繼續添加代碼,如果當我發現新的模式。

+0

你可以捕捉數字** [像](https://regex101.com/r/aD9nV5/1)** – rock321987

回答

1

在JavaScript中,有被稱爲「計算訪問」的操作,進行如object[key],其中object屬性讀取時通過給定表達式的結果確定的,作爲一種替代的正常的.運算符。我個人主要用它來迭代和讀連字符和東西的屬性,b它也可以用來從輸入字符串中獲得相關的想要的結果。
因此,在谷歌搜索整個下午並找出Python語法等之後,我可以編寫一個簡短的程序來完成此操作。

import re 
import string 
h = 0 
r = re.compile(r'(\d+)\s*(\w+)\b') 
def incr(m): 
    h+=m.group(1)*({'in':1,'inches':1,'inch':1,'foot':12,'feet':12,'cm':0.3937,'centimeter':0.3937,'centimeters':0.3937}[string.lower(m.group(2))]||1) # etc. etc. 
    return '' 
re.sub(r, incr, input) 
print h 

您可能希望限制可用於保持dict從得到太大的關鍵字。

+0

謝謝你。我在另一個程序中使用了一個類似的字典進行轉換,但是我只是在用戶輸入數字,所以它更簡單。今天會試試這個 –

5

pyparsing是一個很好的模塊,用於解析這種簡單的情況,尤其是在嘗試處理比預測結果更差但仍然相當結構化的人工輸入時。您可以使用一些友好命名的類(KeywordOptionalOneOrMore等)和算術運算符(序列爲'+',替代品爲'|'等)將分析器組合爲較大的解析器。這裏是一個解析器,由你的示例中的位構建而成(同樣支持「和」,對於英尺和英寸以及分數英尺和英寸值也是如此)(本示例使用最新版本的pyparsing,版本2.1.4):

samples = """\ 
Height 5 feet 9 inch 
5 feet 9 inch 
5ft 9 in 
5feet 9inches 
5'-9-1/2" 
5' 9-1/2" 
5' 9 1/2" 
6' 
3/4" 
3ft-6-1/4 in 
""" 


from pyparsing import CaselessKeyword, pyparsing_common, Optional 

CK = CaselessKeyword 
feet_units = CK("feet") | CK("ft") | "'" 
inch_units = CK("inches") | CK("inch") | CK("in") | '"' 

# pyparsing_common.number will parse an integer or real, and convert to float 
integer = pyparsing_common.number 

fraction = integer + '/' + integer 
fraction.addParseAction(lambda t: t[0]/t[-1]) 

qty = fraction | (integer + Optional(fraction)).addParseAction(lambda t:sum(t)) 

# define whole Height feet-inches expression 
HEIGHT = CK("height") | CK("ht") 
inch_qty = qty("inches") 
feet_qty = qty("feet") 
height_parser = Optional(HEIGHT) + (inch_qty + inch_units | 
           feet_qty + feet_units + Optional(inch_qty + inch_units)) 

# use parse-time callback to convert feet-and-inches to inches 
height_parser.addParseAction(lambda t: t.get("feet", 0.0)*12 + t.get("inches", 0.0)) 

height_parser.ignore("-") 

height_parser.runTests(samples) 

# how to use the parser in normal code 
height_value = height_parser.parseString(samples.splitlines()[0])[0] 
print(height_value, type(height_value)) 

打印:

Height 5 feet 9 inch 
[69.0] 


5 feet 9 inch 
[69.0] 


5ft 9 in 
[69.0] 


5feet 9inches 
[69.0] 


5'-9-1/2" 
[69.5] 


5' 9-1/2" 
[69.5] 


5' 9 1/2" 
[69.5] 


6' 
[72.0] 


3/4" 
[0.75] 


3ft-6-1/4 in 
[42.25] 

69.0 <type 'float'>