是否有ruby方法在其他字符串之间选择字符串?

是否有ruby方法在其他字符串之间选择字符串?,ruby,string,select,methods,extract,Ruby,String,Select,Methods,Extract,我开始编程,我想做一个程序来提取文本中两个单词之间的所有单词,以便将它们存储在变量中 例如,使用“开始和停止”字样: 开始1 2 3停止5 6开始7 8停止9 10 我想存储在变量中:1 2 3 7 8 我开始使用Ruby,正如您在下面的代码中所看到的,我当前的想法是将字符串全局转换为数组,然后对string1和string2的位置进行编号;然后使用初始数组string1+1、…string2-1的值创建一个数组“string1”。 不幸的是,它只工作一次,因为.index函数只在第一次出现时工

我开始编程,我想做一个程序来提取文本中两个单词之间的所有单词,以便将它们存储在变量中

例如,使用“开始和停止”字样: 开始1 2 3停止5 6开始7 8停止9 10

我想存储在变量中:1 2 3 7 8

我开始使用Ruby,正如您在下面的代码中所看到的,我当前的想法是将字符串全局转换为数组,然后对string1和string2的位置进行编号;然后使用初始数组string1+1、…string2-1的值创建一个数组“string1”。 不幸的是,它只工作一次,因为.index函数只在第一次出现时工作……有更好的方法吗

提前感谢您的帮助

text = "0 start 2 3 4 stop 6 7 start 9 10 stop 12"

start= text.split(' ')

a = start.index('start')
b = start.index('stop')

puts a
puts b
puts c = start[a+1,b-a-1].join(" ")

# returns 
#1
#5
#2 3 4 ```






你并没有完全得到一个错误,也许是一个更好的地方去问。但是,由于您是社区中的新手,这里有一个正则表达式,它可以完成这项工作:

text = "0 start 2 3 4 stop 6 7 start 9 10 stop 12"
text.scan(/start ((?:(?!start).)*?) stop/).join(' ')
# => "2 3 4 9 10"
顺便说一句,在Ruby中测试正则表达式的好地方是

我希望这对您有所帮助。

您可以从扫描方法和正则表达式开始:

text = "0 start 2 3 4 stop 6 7 start 9 10 stop 12"
res1 = text.scan(/start\s*(.*?)\s*stop/) #[["2 3 4"], ["9 10"]]
res2 = res1.flatten #["2 3 4", "9 10"]
或者没有中间变量:

res = text.scan(/start(.*?)stop/).flatten #["2 3 4", "9 10"]
说明:

有关扫描方法,请参阅

正则表达式/start\s*?\s*stop/是

开始 \s*:任何空格字符 *?:

并负责记忆内容。 . 表示任意字符,*表示重复零个或多个字符?将结果限制在尽可能短的范围内,详情见下文 \s*:任何空格字符

停止 结果是一个正则表达式命中的数组。正则表达式可以包含用于检测多对的不同部分。所以它是一个数组的数组。在我们的例子中,每个内部数组都有一个元素,所以可以使用flatte来获得一个“flat”数组

如果你不使用这个?在正则表达式中,可以找到2 3 4停止6 7开始9 10,而不是较短的部分。

一个单行方法链 以下是一种基于以下内容的方法:

这里的想法是:

提取在不区分大小写的开始关键字和停止关键字之间括号内的所有字符串段

text.scan /\bstart\s+(.*?)\s+stop\b/i
#=> [["2 3 4"], ["9 10"]]
[["2 3 4"], ["9 10"]].flat_map { _1.flat_map &:split }
#=> ["2", "3", "4", "9", "10"]
从关键字之间提取以空格分隔的单词

text.scan /\bstart\s+(.*?)\s+stop\b/i
#=> [["2 3 4"], ["9 10"]]
[["2 3 4"], ["9 10"]].flat_map { _1.flat_map &:split }
#=> ["2", "3", "4", "9", "10"]
警告 上述方法的注意事项包括:

创建嵌套数组,并且用于处理它们的对的重复调用没有我希望的那么优雅。 \b是零宽度断言,因此查找单词边界可能导致扫描在结果中包含前导和尾随空格,然后需要由或处理。 将\s+替换为\b可在创建其他边缘情况时处理某些边缘情况。 它不做任何事情来防止不平衡对,例如开始0开始2 3 4停止6停止。 对于简单的用例,您可能只需要使用经过调优的正则表达式进行Stringscan。您的输入和数据结构越是多样和不可预测,您的解析例程需要处理的边缘情况就越多。

选择使用数组:作为起点,我建议使用after

根据您的命令和停止语:

command = "START 1 2 3 STOP 5 6 START 7 8 STOP 9 10"

start = 'START'
stop = 'STOP'
您可以这样使用它:

grouped_cmd = command.split.slice_before { |e| [start, stop].include? e } # .to_a
#=> [["START", "1", "2", "3"], ["STOP", "5", "6"], ["START", "7", "8"], ["STOP", "9", "10"]]
然后,您可以随意操纵,例如:

grouped_cmd.select { |first, *rest| first == start }
#=> [["START", "1", "2", "3"], ["START", "7", "8"]]


依此类推。

您可以标记此拆分/\s+/,然后将其切分为开始/停止块。您需要学习正则表达式。
grouped_cmd.each_slice(2).map { |(start, *stt), (stop, *stp)| { start.downcase.to_sym => stt, stop.downcase.to_sym => stp } }
#=> [{:start=>["1", "2", "3"], :stop=>["5", "6"]}, {:start=>["7", "8"], :stop=>["9", "10"]}]