2016-08-23 51 views
1

我想读取包含变量名称和相应值的大型文本文件(请参阅下面的小例子)。名称都是大写字母,值通常用句点和空白字符分隔,但如果变量名称太长,则它仅被空格分隔。从文本文件中使用REGEX在Python中提取变量名称和值

WATER DEPTH ..........  20.00 M  TENSION AT TOUCHDOWN . 382.47 KN 

TOUCHDOWN X-COORD. ... -206.75 M  BOTTOM SLOPE ANGLE ...  0.000 DEG 

PROJECTED SPAN LENGTH  166.74 M  PIPE LENGTH GAIN .....  1.72 M 

我可以使用下面的表达式查找值:

line = ' PROJECTED SPAN LENGTH  166.74 M  PIPE LENGTH GAIN .....  1.72 M \n' 
re.findall(r"[-+]?\d*\.\d+|\d+", line): 
['166.74', '1.72'] 

但是,当我尝试提取变量名称,使用以下的表达式我已经开头和结尾的空格,我想忽略。

re.findall('(?<=\s.)[A-Z\s]+', line) 
[' PROJECTED SPAN LENGTH  ', '  PIPE LENGTH GAIN ', ' ', ' \n'] 

我相信它应该有^ \ s这样的东西,但我不能得到它的工作。 成功时,我想将数据存储在数据框中,变量名称为索引,值为列。

+2

使用'r'[A-Z] +(?:\ s + [A-Z] +)*'' –

回答

0

您可以使用下面的表达re.finditer()一起:

(?P<category>[A-Z][A-Z- ]+[A-Z]) 
[. ]+ 
(?P<value>-?\d[.\d]+)\ 
(?P<unit>M|DEG|KN) 

a demo on regex101.com


Python这将是:

import re 

rx = re.compile(r''' 
    (?P<category>[A-Z][A-Z- ]+[A-Z]) 
    [. ]+ 
    (?P<value>-?\d[.\d]+)\ 
    (?P<unit>M|DEG|KN) 
''', re.VERBOSE) 

string = ''' 
WATER DEPTH ..........  20.00 M  TENSION AT TOUCHDOWN . 382.47 KN 

TOUCHDOWN X-COORD. ... -206.75 M  BOTTOM SLOPE ANGLE ...  0.000 DEG 

PROJECTED SPAN LENGTH  166.74 M  PIPE LENGTH GAIN .....  1.72 M 
''' 

matches = [(m.group('category'), m.group('value'), m.group('unit')) \ 
      for m in rx.finditer(string)] 
print(matches) 
# [('WATER DEPTH', '20.00', 'M'), ('TENSION AT TOUCHDOWN', '382.47', 'KN'), ('TOUCHDOWN X-COORD', '-206.75', 'M'), ('BOTTOM SLOPE ANGLE', '0.000', 'DEG'), ('PROJECTED SPAN LENGTH', '166.74', 'M'), ('PIPE LENGTH GAIN', '1.72', 'M')] 

a demo on ideone.com

+0

谢谢Jan,这是一个非常整洁的解决方案,regex101.com也非常方便。因此,我冒昧地向你提出另一个问题,我希望给出问题的链接[link] https://regex101.com/r/nK3hN6/1在我之前的问题中,我只发布了一部分要分析的文字,但还有一些线条,我也有一些困难。例如,没有单位的线路。在此先感谢 – EmielT

+0

@EmielT:https://regex101.com/r/nK3hN6/2(使最后一组可选,并把最长的替代方案先。 – Jan

+0

完美,非常感谢!它给了我至少更多的洞察力正则表达式。 – EmielT

0

使用[A-Z]{2,}(?:\s+[A-Z]+)*

[A-Z]{2,}查找大写单词至少2在长度

(?:\s+[A-Z]+)*为如果在该标签的多个词的捕获组

EDIT

要在你的评论中处理案例我推荐:

[A-Z-\/]{2,}(?:\s*[A-Z-\/]+(?:\.)*)* 

只要确保至少有一个空间在R.O.W.最后一期后前...

[A-Z-\/]{2,}将检查大写字母, - ,和2长度或更大

(?:\s*[A-Z-\/]+(?:\.)*)* /是用于多个单词和/或其中包含句点的单词的捕获组

+0

感谢depperm,这个工作得很好。但是,对于最后一行_TOUCHDOWN X-COORD._正在分割为_TOUCHDOWN_和_COORD_。好的,这可以通过转义非捕获组中的字符来解决。但是在文本文件中也可能会出现以下情况:空气中的重量/长度。 1301。00 N/M屈服应力......... 241.00 MPA或BARGE HEADING ........ 0.000°OFF。 ... 0.00 M.这里R.O.W.例如没有找到,我相信可以通过使用lookbehind/lookahead语句来捕获。你能否就如何实现这一点提供建议?谢谢 – EmielT

+0

@EmielT编辑我的回答 – depperm

0

如果您曾想要取出前导空白/尾部空白,则可以使用.strip()方法。

Python String strip

stripped_values = [raw.strip() for raw in re.findall('(?<=\s.)[A-Z\s]+', line)] 
相关问题