2017-06-20 113 views
0

我想使用正则表达式分割字符串。我需要在nifi中使用正则表达式来将字符串分组。任何人都可以帮助我如何使用正则表达式分割字符串下面。字符串与空间使用正则表达式分割

或者我们如何给出特定的分隔符号来分割字符串。例如,在下面的字符串中,如何指定我希望在第三次出现空格后使用字符串。

假设我有一个字符串

"6/19/2017 12:14:07 PM 0FA0 PACKET 0000000DF5EC3D80 UDP Snd 11.222.333.44 93c8 R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in-addr(4)arpa(0)" 


我想结果是这样的:

group 1 - 6/19/2017 12:14:07 PM 
group 2 - 0FA0 
group 3 - PACKET 0000000DF5EC3D80 
group 4 - UDP 
group 5 - Snd 
group 6 - 11.222.333.44 
group 7 - 93c8 
group 8 - R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in- 
      addr(4)arpa(0) 


谁能帮我。提前致谢。

+1

您是否在寻找某件事[像这样](https://regex101.com/r/qFE95M/3)? – horcrux

+0

我做了这样的事情,如果数据的格式不固定,只有空格是值得信任的:https://regex101.com/r/OikYiX/1只使用所需的组。如果以'AM'或'PM'结尾的日期是固定的,那么('''UDP','Snd'等等)中的char数量等等。你可以在@horcrux这样的正则表达式中更具体。 – Esteban

+0

感谢你们的回复。 Horcrux建议的第一个表达式工作得很好。 Esteban建议的第二个表达式对于给定的字符串是有效的,但是如果在任何组中有任何长度变化,那么它会中断。 是的,格式不固定,所以我们只能信任空格分隔符。 非常感谢您的帮助。 – ankit

回答

1

如果这是真的,你想为分隔符,你可以做这样的事情,以避免固定宽度的噩梦只是某些空间:

regex = "(\S+\s\S+\s\S+)\s(\S+)\s(\S+\s\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(.*)" 

差不多它是什么样子的,非空间组\ S +与空格\ s和每个与parans组合。 *末尾只是线路的其余部分,可根据需要进行调整。如果你想让每个组成为每个非间隔组,你可以做一个拆分而不是正则表达式,但看起来这不是我们想要的。我无法使用nifi来测试,但这里是Python中的一个例子。

import re 

text = "6/19/2017 12:14:07 PM 0FA0 PACKET 0000000DF5EC3D80 UDP Snd 11.222.333.44 93c8 R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in-addr(4)arpa(0)" 
regex = "(\S+\s\S+\s\S+)\s(\S+)\s(\S+\s\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(.*)" 

match = re.search(regex, text) 
print ("group 1 - " + match.group(1)) 
print ("group 2 - " + match.group(2)) 
print ("group 3 - " + match.group(3)) 
print ("group 4 - " + match.group(4)) 
print ("group 5 - " + match.group(5)) 
print ("group 6 - " + match.group(6)) 
print ("group 7 - " + match.group(7)) 
print ("group 8 - " + match.group(8)) 

输出:

group 1 - 6/19/2017 12:14:07 PM 
group 2 - 0FA0 
group 3 - PACKET 0000000DF5EC3D80 
group 4 - UDP 
group 5 - Snd 
group 6 - 11.222.333.44 
group 7 - 93c8 
group 8 - R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in-addr(4)arpa(0) 
+1

感谢您的回复。这个表达方式运作良好。感谢您的帮助。 – ankit

0

你们是不是要每个组提取到一个单独的属性?这对于“纯粹”的NiFi来说当然是可能的,但是对于这样长的线条,使用ExecuteScript处理器可以更有意义地使用Groovy或Python的更复杂的正则表达式处理,并与String#split()结合使用,并提供发布的脚本


要执行使用ExtractText这个任务,你会因为如下步骤进行设置:

ExtractText processor configuration

可复制的模式:

group 1: (^\S+\s\S+\s\S+) 
group 2: (?i)(?<=\s)([a-f0-9]{4})(?=\s) 
group 3: (?i)(?<=\s)(PACKET\s[a-f0-9]{4,16})(?=\s) 
group 4: (?i)(?<=\s\S{16}\s)([\w]{3,})(?=\s) 
group 5: (?i)(?<=\s.{3}\s)([\w]{3,})(?=\s) 
group 6: (?i)(?<=\s.{3}\s)([\d\.]{7,15})(?=\s) 
group 7: (?i)(?<=\d\s)([a-f0-9]{4})(?=\s) 
group 8: (?i)(?<=\d\s[a-f0-9]{4}\s)(.*)$ 

需要注意的是Include Capture Group 0设置是非常重要的到false。由于在NiFi中验证正则表达式的方式(目前所有正则表达式必须至少有一个捕获组 - 将使用NIFI-4095 | ExtractText should not require a capture group in every regular expression修复),您将得到重复组(group 1group 1.1)。

产生的flowfile具有正确填充的属性:Populated flowfile attributes

完整的日志输出:

2017-06-20 14:45:57,050 INFO [Timer-Driven Process Thread-9] o.a.n.processors.standard.LogAttribute LogAttribute[id=c6b04310-015c-1000-b21e-c64aec5b035e] logging for flow file StandardFlowFileRecord[uuid=5209cc65-08fe-44a4-be96-9f9f58ed2490,claim=StandardContentClaim [resourceClaim=StandardResourceClaim[id=1497984255809-1, container=default, section=1], offset=444, length=148],offset=0,name=1920315756631364,size=148] 
-------------------------------------------------- 
Standard FlowFile Attributes 
Key: 'entryDate' 
    Value: 'Tue Jun 20 14:45:10 EDT 2017' 
Key: 'lineageStartDate' 
    Value: 'Tue Jun 20 14:45:10 EDT 2017' 
Key: 'fileSize' 
    Value: '148' 
FlowFile Attribute Map Content 
Key: 'filename' 
    Value: '1920315756631364' 
Key: 'group 1' 
    Value: '6/19/2017 12:14:07 PM' 
Key: 'group 1.1' 
    Value: '6/19/2017 12:14:07 PM' 
Key: 'group 2' 
    Value: '0FA0' 
Key: 'group 2.1' 
    Value: '0FA0' 
Key: 'group 3' 
    Value: 'PACKET 0000000DF5EC3D80' 
Key: 'group 3.1' 
    Value: 'PACKET 0000000DF5EC3D80' 
Key: 'group 4' 
    Value: 'UDP' 
Key: 'group 4.1' 
    Value: 'UDP' 
Key: 'group 5' 
    Value: 'Snd' 
Key: 'group 5.1' 
    Value: 'Snd' 
Key: 'group 6' 
    Value: '11.222.333.44' 
Key: 'group 6.1' 
    Value: '11.222.333.44' 
Key: 'group 7' 
    Value: '93c8' 
Key: 'group 7.1' 
    Value: '93c8' 
Key: 'group 8' 
    Value: 'R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in-addr(4)arpa(0)' 
Key: 'group 8.1' 
    Value: 'R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in-addr(4)arpa(0)' 
Key: 'path' 
    Value: './' 
Key: 'uuid' 
    Value: '5209cc65-08fe-44a4-be96-9f9f58ed2490' 
-------------------------------------------------- 
6/19/2017 12:14:07 PM 0FA0 PACKET 0000000DF5EC3D80 UDP Snd 11.222.333.44 93c8 R Q [8085 A DR NOERROR] PTR (2)73(3)191(3)250(2)10(7)in-addr(4)arpa(0) 

与NiFi 1.3.0的发布另一种选择是使用record processing capabilities。这是一项新功能,它允许任意输入格式(Avro,JSON,CSV等)以流方式进行分析和操作。 Mark Payne编写了一个very good tutorial here,介绍了该功能并提供了一些简单的演练。

+0

感谢您的回复。这个表达式工作正常。我已经看到,在每一行表达式中,您都固定了长度,但是其他记录的长度可能不一样。将只有分隔符是空间。我不知道每个组的长度是多少。它可以变化。请你让我知道可以使输出组基于空格的表达式。 – ankit

+0

这将是非常困难的。使用'ExecuteScript'和'split()'可以获得更多成功,然后将元素重构为所需的字符串。 – Andy

+0

您还可以使用记录解析功能 - Bryan Bende只是[使用Grok - > JSON发布了一个示例](http://bryanbende.com/development/2017/06/20/apache-nifi-records-and-schema这是您的问题的最佳选择。 – Andy