[英]ruby multiline scan between ; and negate?
我正在尝试匹配文本;-
。
我用了:
inputx.scan(/;-.+?\n[^\n]*;-/)
但它不起作用。
我的文字是:
baseball;-1
norm;4
dad;3
soda;1
robot;-8
mmm;3
fly;-1
cat;4
bird;4
dragon;6
mor;-1
我需要将文本分开;-
。
例如,这是结果数组的第一个元素:
baseball;-1
norm;4
dad;3
soda;1
robot;-8
这是第二个:
fly;-1
cat;4
bird;4
dragon;6
mor;-1
您可以使用Array#split
两次,第一次按行分割,第二次根据是否存在分割;
或;-
(使用模式/;-?/
)
模式/;-?/
匹配分号后跟可选-
。
inputx.split("\n").map{|s| s.split(/;-?/)}
#=> [[" baseball", "1"], [" norm", "4"], [" dad", "3"], [" soda", "1"], [" robot", "8"], [" mmm", "3"], [" fly", "1"], [" cat", "4"], [" bird", "4"], [" dragon", "6"], [" mor", "1"]]
您可以使用匹配任何以-
和1位或更多位数结尾的行的正则表达式,然后将任何文本匹配到以-
结尾的第一行-
和1位或更多位数:
/.*-\d+$(?m:.*?-\d+$)/
请参阅Rubular演示
细节 :
.*-\\d+$
- 除了换行符之外的任何0 .*-\\d+$
字符,后跟-
和1+位数 (?m:.*?-\\d+$)
- 一个修饰符组.
匹配换行符匹配:
.*?
- 任何0+字符,尽可能少 -
- 连字符 \\d+
- 1位或更多位数 $
- 行尾。 具有scan
或split
模式会导致正则表达式不必要地复杂化,因为它不是问题框中的最佳工具。
我会用这样的东西:
text = <<EOT
baseball;-1
norm;4
dad;3
soda;1
robot;-8
mmm;3
fly;-1
cat;4
bird;4
dragon;6
mor;-1
EOT
ary = [[]]
text.lines.each do |l|
if l[';-'] ... l[';-']
ary.last << l
else
ary << []
end
end
ary
# => [[" baseball;-1\n",
# " norm;4\n",
# " dad;3\n",
# " soda;1\n",
# " robot;-8\n"],
# [" fly;-1\n",
# " cat;4\n",
# " bird;4\n",
# " dragon;6\n",
# " mor;-1\n"]]
如果您不想尾随新行:
ary = [[]]
text.lines.map(&:chomp).each do |l|
if l[';-'] ... l[';-']
ary.last << l
else
ary << []
end
end
ary
# => [[" baseball;-1", " norm;4", " dad;3", " soda;1", " robot;-8"],
# [" fly;-1", " cat;4", " bird;4", " dragon;6", " mor;-1"]]
如果你不想要每个元素周围的空格:
ary = [[]]
text.lines.map(&:strip).each do |l|
if l[';-'] ... l[';-']
ary.last << l
else
ary << []
end
end
ary
# => [["baseball;-1", "norm;4", "dad;3", "soda;1", "robot;-8"],
# ["fly;-1", "cat;4", "bird;4", "dragon;6", "mor;-1"]]
这是如何运作的? ..
和...
运算符根据它是在Range的上下文中使用还是在if
条件中更改含义。 ..
被称为“触发器”操作符,它在满足第一个条件时改变状态。 它将在那时开始返回true
,并将继续这样做,直到满足第二个条件,此时它再次开始返回false。 这样可以很容易地查找某些内容,然后开始对后续行进行操作,直到第二个条件发生。
通常我们会使用不同的条件,例如在文件的一行中搜索“begin”和“end”。 但在这种情况下,我们需要它不立即切换,因为开始和结束条件都是相同的,这就是...
来的地方。 它在测试第二个条件之前等待一个循环,允许此代码继续,找到下一行直到“关闭” ';-'
。 我不得不说,这个数据集是我见过的最奇怪的数据集之一。 (最奇怪的是几年前旧电子邮件程序中的地址簿的一些二进制数据)。 我会关注产生它的过程,如果那一代在我的控制下,我会改变它以使用更标准的东西。
我们可以使用Enumerable#chunk和Ruby的触发器操作符 。 这不需要使用正则表达式。 str
是OP给出的字符串。
arr = str.lines.chunk do |line|
true if line.include?('-') ... line.include?('-')
end.select(&:first).map { |_,a| a.join }
#=> ["baseball;-1\nnorm;4\ndad;3\nsoda;1\nrobot;-8\n",
# "fly;-1\ncat;4\nbird;4\ndragon;6\nmor;-1\n"]
arr.each { |s| puts "\n"; puts s }
baseball;-1
norm;4
dad;3
soda;1
robot;-8
fly;-1
cat;4
bird;4
dragon;6
mor;-1
在触发器表达中需要使用三个(不是两个)点(在上面给出的参考中搜索“三个点”)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.