【问题标题】:Regex to exclude a specific value in key-value pairs with same pattern正则表达式以排除具有相同模式的键值对中的特定值
【发布时间】:2021-12-29 01:30:54
【问题描述】:

从下面的文本中,我将只捕获FCST VA CLD +6HR/12HR/18HR: 之后的数据。为此,我构建了一个正则表达式,它提供了我想要的数据,但它也提供了OBS VA CLD 之后我不想要的数据。

请注意,这些字段可能会被报告或不被报告。

我正在使用https://regex101.com/r/EPxUHG/2

([\d]+/[\d\w]+)?\s?([\w]+/[\w\d]+)\s((?:[\w]{1}[\d]{4}\s[\w]{1}[\d]{5}\s\-\s)+[\w]{1}[\d]{4}\s[\w]{1}[\d]{5})

文字是

VA ADVISORY
STATUS: EXER
DTG: 20211116/0600Z
VAAC: LONDON
VOLCANO: EYJAFJALLAJOKULL 372020
PSN: N6338 W01938
AREA: ICELAND
SUMMIT ELEV: 1651M
ADVISORY NR: 2021/009
INFO SOURCE: ICELAND MET OFFICE
AVIATION COLOUR CODE: RED
ERUPTION DETAILS: EXERCISE VOLCEX21 - EYJAFJALLAJOKULL ERUPTION
OBS VA DTG: 16/0600Z
OBS VA CLD: SFC/FL200 N4550 W04415 - N6356 W01927 - N7353 E05847 -
N4025 E05735 - N4550 W04415 MOV SE 15KT FL200/350 N5343 W03145 -
N6355 W01932 - N7446 E05944 - N6250 E05925 - N5255 W02531 - N5343
W03145 MOV SE 40KT
FCST VA CLD +6 HR: 16/1200Z SFC/FL200 N4517 W04623 - N6356 W01924 -
N7750 E07729 - N3856 E06031 - N4517 W04623 FL200/350 N4839 W04904 -
N7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904
FCST VA CLD +12 HR: 16/1800Z SFC/FL200 N4010 E03817 - N4900 W04529 -
N7112 W00641 - N7617 E09941 - N4010 E03817 FL200/350 N4919 W05700 -
N7300 E03329 - N7732 E09626 - N5936 E09143 - N4919 W05700
FCST VA CLD +18 HR: 17/0000Z SFC/FL200 N4901 W05420 - N7235 E00056 -
N7558 E09708 - N3934 E05131 - N4901 W05420 FL200/350 N4933 W03842 -
N5436 W04127 - N7433 E03732 - N7935 E11430 - N6503 E10238 - N4933
W03842
RMK: EXERCISE VOLCEX21 - EYJAFJALLAJOKULL ERUPTION CONTINUES,
RECENTLY INCREASING TO APPROX 8KM
NXT ADVISORY: NO LATER THAN 20211116/1200Z

编辑:更具体地说,我修改了示例和正则表达式。如您所见,我可以获得写入名为 FCST VA CLD +6 HR: / FCST VA CLD +12 HR: / FCST VA CLD +18 HR: 的字段中的所有信息。 每个字段(FCST VA CLD +6 HR: / FCST VA CLD +12 HR: / FCST VA CLD +18 HR:) 必须是一个匹配项,并且每个匹配项必须分成不同的组。

  • 第一组:是发布时间(16/1200Z、16/1800Z、17/0000Z)。 每个字段只有一个发布时间。
  • 第二组:是层(SFC/FL200、FL200/350)。我不知道会报告多少层,但至少有一层可用。如果报告了多个层,则它们总是被引用到相同的发布时间(每个字段)
  • 第三组:它们是坐标。一堆坐标是 总是指单层。
匹配 1:16/1200Z SFC/FL200 N4517 W04623 - N6356 W01924 - N7750 E07729 - N3856 E06031 - N4517 W04623 FL200/350 N4839 W04904 -N7025 E01017 - N7509 E07954 - N4839 E07954 - N4861 第一组:16/1200Z 第二组:SFC/FL200 第三组:N4517 W04623 - N6356 W01924 - N7750 E07729 - N3856 E06031 - N4517 W04623 第二组:FL200/350 第三组:N4839 W04904 - N7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904 匹配 2: 16/1800Z SFC/FL200 N4010 E03817 - N4900 W04529 - N7112 W00641 - N7617 E09941 - N4010 E03817 FL200/350 N4919 W05700 - N7300 E03329 - N7732 E09623 - N4139 E09623 - N95 第一组:16/1800Z 第二组:SFC/FL200 第三组:N4010 E03817 - N4900 W04529 - N7112 W00641 - N7617 E09941 - N4010 E03817 第二组:FL200/350 第三组:N4919 W05700 - N7300 E03329 - N7732 E09626 - N5936 E09143 - N4919 W05700 匹配3:17 / 0000ZSFC / FL200 N4901 W05420 - N7235 E056 - N3934 E05131 - N3934 E05131 - N4901 W05420 FL200 / 350 N4933 W03842 - N5436 W03732 - N7433 E03732 - N7935 E11430 - N6503 E10238 - N4933 W03842 第一组:17/0000Z 第二组:SFC/FL200 第三组:N4901 W05420 - N7235 E00056 -N7558 E09708 - N3934 E05131 - N4901 W05420 第二组:FL200/350 第三组:N4933 W03842 -N5436 W04127 - N7433 E03732 - N7935 E11430 - N6503 E10238 - N4933 W03842

我修改过的正则表达式:

([\d]+/[\d\w]+\s)(([\w\d]+/[\w\d]+)\s((?:[\w]{1}[\ d]{4}\s[\w]{1}[\d]{5}\s\-\s)+[\w]{1}[\d]{4}\s[\w]{ 1}[\d]{5}\s))+

问题,你可以在这里看到:https://regex101.com/r/VZG3IA/1

是我无法获得第一层(SFC/FL200)而只能获得第二层(FL200/350)

如何更正我的正则表达式以获得我想要的数据?能不能写得更好?

预期的输出是这样的:

[('16/1200Z', ('SFC/FL200', 'N4517 W04623 - N6356 W01924 - N7750 E07729 - N3856 E06031 - N4517 W04623'), (FL200/350, N4839 W04904 - N7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904))]

[('16/1800Z', ('SFC/FL200', 'N4010 E03817 - N4900 W04529 - N7112 W00641 - N7617 E09941 - N4010 E03817'), (FL200/350, N4919 W05700 - N73320 E03326 - N76 N5936 E09143 - N4919 W05700))]

[('17/0000Z', ('SFC/FL200', 'N4901 W05420 - N7235 E00056 -N7558 E09708 - N3934 E05131 - N4901 W05420'), (FL200/350, N4933 W03842 -N54336 W04127 - N7 N7935 E11430 - N6503 E10238 - N4933 W03842))]

甚至更好的是这样的 json 文件(不确定它是否格式正确):
{ "issue time":{
        "16/1200Z": {
            "layer" : {
                "SFC/FL200":{N4517 W04623 - N6356 W01924 - N7750 E07729 - N3856 E06031 - N4517 W04623}
                "FL200/350":{N4839 W04904 - N7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904}
                  }
                }
        }
}

{ "issue time":{
        "16/1800Z": {
            "layer" : {
                "SFC/FL200":{N4010 E03817 - N4900 W04529 - N7112 W00641 - N7617 E09941 - N4010 E03817}
                "FL200/350":{N4919 W05700 - N7300 E03329 - N7732 E09626 - N5936 E09143 - N4919 W05700}
                  }
                }
        }
}

{ "issue time":{
        "17/0000Z": {
            "layer" : {
                "N4901 W05420 - N7235 E00056 -N7558 E09708 - N3934 E05131 - N4901 W05420}
                "N4933 W03842 -N5436 W04127 - N7433 E03732 - N7935 E11430 - N6503 E10238 - N4933 W03842}
                }       
                }
        }
}

【问题讨论】:

  • 您想在这里看到的确切输出是什么?不知道这一点我们无法回答。
  • 不幸的是,这对我没有帮助
  • 最清楚的方式是显示你想要做的事情是显示 Python 对象(例如字符串列表),它是示例所需的结果,最好是显示的数量和长度示例中的行减少了。例如,我认为没有理由超过 10 行。顺便说一句,[\w]{1}\w{1} 相同,\w 相同。
  • 首先,不要在手工制作的正则表达式中使用{1},这是多余的。 [\d][\w] 应始终写为\d\w,这样可以避免进一步混淆,只有当您希望向字符类添加更多字符时才需要括号。现在,没有这些额外“装饰器”的模式看起来像 (\d+/\w+\s)((\w+/\w+)\s((?:\w\d{4}\s\w\d{5}\s-\s)+\w\d{4}\s\w\d{5}\s))+,如果你向其中添加命名组并将其与 PyPi 正则表达式库一起使用,那么你可以获得...
  • this.

标签: python python-3.x regex


【解决方案1】:

你可以使用

import regex

text = "VA ADVISORY\nSTATUS: EXER\nDTG: 20211116/0600Z\nVAAC: LONDON\nVOLCANO: EYJAFJALLAJOKULL 372020\nPSN: N6338 W01938\nAREA: ICELAND\nSUMMIT ELEV: 1651M\nADVISORY NR: 2021/009\nINFO SOURCE: ICELAND MET OFFICE\nAVIATION COLOUR CODE: RED\nERUPTION DETAILS: EXERCISE VOLCEX21 - EYJAFJALLAJOKULL ERUPTION\nOBS VA DTG: 16/0600Z\nOBS VA CLD: SFC/FL200 N4550 W04415 - N6356 W01927 - N7353 E05847 -\nN4025 E05735 - N4550 W04415 MOV SE 15KT FL200/350 N5343 W03145 -\nN6355 W01932 - N7446 E05944 - N6250 E05925 - N5255 W02531 - N5343\nW03145 MOV SE 40KT\nFCST VA CLD +6 HR: 16/1200Z SFC/FL200 N4517 W04623 - N6356 W01924 -\nN7750 E07729 - N3856 E06031 - N4517 W04623 FL200/350 N4839 W04904 -\nN7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904\nFCST VA CLD +12 HR: 16/1800Z SFC/FL200 N4010 E03817 - N4900 W04529 -\nN7112 W00641 - N7617 E09941 - N4010 E03817 FL200/350 N4919 W05700 -\nN7300 E03329 - N7732 E09626 - N5936 E09143 - N4919 W05700\nFCST VA CLD +18 HR: 17/0000Z SFC/FL200 N4901 W05420 - N7235 E00056 -\nN7558 E09708 - N3934 E05131 - N4901 W05420 FL200/350 N4933 W03842 -\nN5436 W04127 - N7433 E03732 - N7935 E11430 - N6503 E10238 - N4933\nW03842\nRMK: EXERCISE VOLCEX21 - EYJAFJALLAJOKULL ERUPTION CONTINUES,\nRECENTLY INCREASING TO APPROX 8KM\nNXT ADVISORY: NO LATER THAN 20211116/1200Z"

pattern = r'(?P<issuetime>\d+/\w+\s)(?:(?P<layer>\w+/\w+)\s(?P<coordinates>(?:\w\d{4}\s\w\d{5}\s-\s)+\w\d{4}\s\w\d{5}\s))+'

for m in [x.capturesdict() for x in regex.finditer(pattern, text)]:
    print(m)

请参阅Python demo online。输出:

{'issuetime': ['16/1200Z '], 'layer': ['SFC/FL200', 'FL200/350'], 'coordinates': ['N4517 W04623 - N6356 W01924 -\nN7750 E07729 - N3856 E06031 - N4517 W04623 ', 'N4839 W04904 -\nN7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904\n']}
{'issuetime': ['16/1800Z '], 'layer': ['SFC/FL200', 'FL200/350'], 'coordinates': ['N4010 E03817 - N4900 W04529 -\nN7112 W00641 - N7617 E09941 - N4010 E03817 ', 'N4919 W05700 -\nN7300 E03329 - N7732 E09626 - N5936 E09143 - N4919 W05700\n']}
{'issuetime': ['17/0000Z '], 'layer': ['SFC/FL200', 'FL200/350'], 'coordinates': ['N4901 W05420 - N7235 E00056 -\nN7558 E09708 - N3934 E05131 - N4901 W05420 ', 'N4933 W03842 -\nN5436 W04127 - N7433 E03732 - N7935 E11430 - N6503 E10238 - N4933\nW03842\n']}

PyPi 正则表达式模块(与pip install regex 一起安装)可以访问每个捕获组内的所有捕获。 (?P&lt;issuetime&gt;\d+/\w+\s)(?:(?P&lt;layer&gt;\w+/\w+)\s(?P&lt;coordinates&gt;(?:\w\d{4}\s\w\d{5}\s-\s)+\w\d{4}\s\w\d{5}\s))+' 正则表达式还具有命名组,这使得可以在每次匹配时使用匹配数据对象的 capturesdict() 来在一个不错的列表中获取命名捕获。

【讨论】:

  • 太完美了。谢谢你。但是,当我尝试您的解决方案时,我遇到了一个我没有考虑到的问题。 FCST VA CLD +6 HR: / FCST VA CLD +12 HR: / FCST VA CLD +18 HR: 字段中的一个或多个值与正则表达式不匹配,因为它们可能包含 NOT AVBL。例如:FCST VA CLD +6 HR: 16/1200Z SFC/FL200 N4517 W04623 - N6356 W01924 FCST VA CLD +12 HR: 16/1800Z NOT AVBL FCST VA CLD +18 HR: 17/0000Z NOT AVBL 如何更正我的正则表达式?
  • @Lareth 抱歉,我不太确定您期望的完全匹配结构。只是猜测this
  • 能确认一下json结构吗?我期待类似:{“issuetime”:{“16/1200Z”:{“layer”:{“SFC/FL200”:{“坐标”:“N4517 W04623 - N6356 W01924 -\nN7750 E07729 - N3856 E06031 - N4517 W04623"} "FL200/350": { "coordinates": "N4839 W04904 -\nN7025 E01017 - N7505 E07954 - N6139 E06549 - N4839 W04904\n"} } } } }其中层是发布时间的值和坐标是图层的值。类似于嵌套结构的东西。
  • @Lareth 您需要“手动”构建它,因为正则表达式只是提取文本字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多