我有一个如下所示的数据文件:
Things
├── Foo
│ ├── 1. Item One
│ ├── 2. Item Two
│ ├── 3. Item Three
│ ├── 4. Item Four
│ ├── 5. Item Five
│ └── 6. Item Six
├── Bar
│ ├── 1. Item Seven
│ ├── 2. Item Eight
│ ├── 3. Item Nine
我要做的是找到某个字符串,与之关联的数字,以及作为('Foo'或'Bar')一部分的子标题
获取项目和数字非常容易:
str = "Item One"
data.each_line do |line|
if line =~ /#{str}/
/(?<num>\d).\s(?<item>.*)/ =~ line
end
end
但我不确定如何获得副标题。我的想法是,一旦我找到了这条线,我可以使用这个数字从那一点算起来。是否有读取线或搜索命令或某些可以执行此操作的命令?
感谢帮助!
答案 0 :(得分:9)
我想出了以下内容,这似乎有效:
data = <<-EOF
Things
├── Foo
│ ├── 1. Item One
│ ├── 2. Item Two
│ ├── 3. Item Three
│ ├── 4. Item Four
│ ├── 5. Item Five
│ └── 6. Item Six
├── Bar
│ ├── 1. Item Seven
│ ├── 2. Item Eight
│ ├── 3. Item Nine
EOF
str = "Item One"
data.lines.each_with_index do |line, i|
if /(?<num>\d)\.\s+#{str}/ =~ line
/(?<var>\w+)/ =~ data.lines[i - (n = $~[:num]).to_i]
p [n, str, var] # ["1", "Item One", "Foo"]
end
end
需要 (n = $~[:num])
来存储从
num
的值
if /(?<num>\d)\.\s+#{str}/ =~ line
入变量(比如n
)为last match data,由全局变量代表的$~
,将取入的语句处的下一个正则表达式匹配过程中被覆盖
/(?<var>\w+)/ =~ data.lines[i - (num = $~[:num]).to_i]
除非我们存储以供日后使用,否则我们将丢失捕获的值num
。
答案 1 :(得分:2)
这是另一种方式(使用@ Wand的data
):
LAZY_T = "├── "
target = "Item Four"
str = data.split(/\n#{LAZY_T}/).find { |s| s =~ /\b#{target}\b/ }
str && [str[/[a-zA-Z]+/], str[/(\d+)\.\s#{target}\b/,1]]
#=> ["Foo", "4"]
如果有的话,第一行会提取字符串的适用部分("Foo"
或"Bar"
)。第二行提取两个所需元素。
注意:
LAZY_T.split('').map(&:ord)
#=> [9500, 9472, 9472, 32]