我有一个文本数据集,我需要把它解析成多个“组”。组是数字标识符。我遇到的问题是,这个数据集中的每个“客户”都有一组未知的数据,并且在用于标识它们的最初两行之后,还有一些附加的行。
例如:
CUSTOMER|100000|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
REBOUND||||||||||
INFO||||||||||
CUSTOMER|100001|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||142||||
INFO||||||||||
CUSTOMER|100002|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
INFO||||||||||
PRE||||||||||
INFO||||||||||
所以在这个例子中,我想删除值为142的客户。在接近尾端的付款行中,可以看到客户100001的值为142。
我一直在用Ruby,但我愿意用任何方法来完成这项工作所以最初,我写了这样一段话:
CUSTOMER\|.*\|142\|.+?(?=\nCUSTOMER)
使用m标志,它寻找客户,然后寻找142,然后做一个积极的展望,直到它再次看到客户。问题在于,regex正在识别找到的初始客户(100000),并继续向下搜索文件,直到找到142,然后停止。我需要的是,如果regex在看到142之前再次看到customer这个词,它就停止运行。|
我试着在
CUSTOMER\|.*(?!CUSTOMER)
但这仍然给了我完整的结果我不确定消极展望与贪婪的字符匹配是如何工作的,但我假设它会说“如果在某个时刻我发现了这个失败点,这就不是匹配”
从那以后,我尝试了一些其他的解决方案,并对此进行了一些尝试:
(?!.*(?:\|142\|))
但我也没得到什么我仍然无法阻止第一个客户分组到第二个客户。思想?
最佳答案
我宁愿分两步而不是一步这使得解决方案更容易理解、测试和维护,而且可能在效率方面is a wash。
首先,让str
保持从文件中读取的字符串。
str =<<BITTER_END
CUSTOMER|100000|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
REBOUND||||||||||
INFO||||||||||
CUSTOMER|100001|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||142||||
INFO||||||||||
CUSTOMER|100002|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
INFO||||||||||
PRE||||||||||
INFO||||||||||
BITTER_END
第一步使用正则表达式将
str
拆分为一个字符串数组,每个字符串对应一个客户。r = /
(?<=^) # Match a beginning of line anchor in a positive lookbehind
(?=CUSTOMER\|) # Match 'CUSTOMER|' in a positive lookahead
/x # Free-spacing regex definition mode
注意,当与String#split一起使用时,此正则表达式会断开字符之间的字符串,即在换行符之后和字符串
'CUSTOMER|'
之前。我已经使用了自由间隔模式使regex自我文档化。按照惯例,它会被写下来
r = /(?<=^)(?=CUSTOMER\|)/
现在让我们把
str
分成几个组。a0 = str.split(r)
为了更容易看到返回值,让我分别打印
a0
的每个元素。a0.size.times { |i| puts "\n#{a0[i]}" }
CUSTOMER|100000|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
REBOUND||||||||||
INFO||||||||||
CUSTOMER|100001|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||142||||
INFO||||||||||
CUSTOMER|100002|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
INFO||||||||||
PRE||||||||||
INFO||||||||||
第二步删除
a0
中包含字符串'|142|'
的元素。a1 = a0.reject { |s| s.include?('|142|') }
a1.size.times{i |放入“\n#{a1[i]}”}
CUSTOMER|100000|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
REBOUND||||||||||
INFO||||||||||
CUSTOMER|100002|Last|First|20171200-000000|20171200-000000|||||||||||||N|||
PAYMENTS|||1234|1234|20171200-000000|20171200-000000||||||||||||1||||
INFO||||||||||
PRE||||||||||
INFO||||||||||
当然,我们会用通常的方式把这两个步骤联系起来。
str.split(r).reject { |s| s.include?('|142|') }
如果返回值是一个字符串,则将
.join
钉在上面的末尾(我从问题的陈述中看不清楚。)关于ruby - 多行/未知数据正则表达式查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48392727/