在 Ruby 中找到第 n 次出现的变量正则表达式?



为问题所说的内容编写方法,需要找到特定左括号的第n次出现的索引(由用户定义,即如果用户提供带有附加参数"{"和"5"的字符串,它将找到第5次出现,与"("和"["(相同(。

目前使用 while 循环并比较每个字符,但这看起来很丑并且不是很有趣,有没有办法用正则表达式做到这一点?您可以在正则表达式中使用变量吗?

def _find_bracket_n(str,left_brac,brackets_num)
i = 0
num_of_left_bracs = 0
while i < str.length && num_of_left_bracs < brackets_num
num_of_left_bracs += 1 if str[i] == left_brac
i += 1
end
n_th_lbrac_index = i - 1
end

需要字符串中给定字符的第n个实例的偏移量,如果字符串包含的实例少于n个,则需要nil偏移量。我将给出四个解决方案。

chr = "("
str = "a(b(cd((ef(g(hi(" 
n = 5

使用枚举#find_index

str.each_char.find_index { |c| c == chr && (n = n-1).zero? }
#=> 10

使用正则表达式

chr_esc = Regexp.escape(chr)
#=> "\("
r = /
A           # match the beginning of the string
(?:          # begin a non-capture group
.*?        # match zero or more characters lazily
#{chr_esc} # match the given character
)            # end the non-capture group
{#{n-1}}     # perform the non-capture group `n-1` times
.*?          # match zero or more characters lazily
#{chr_esc}   # match the given character
/x           # free-spacing regex definition mode
#=> /
A           # match the beginning of the string
(?:          # begin a non-capture group
.*?        # match zero or more characters lazily
(         # match the given character
)            # end the non-capture group
{4}          # perform the non-capture group `n-1` times
.*?          # match zero or more characters lazily
(           # match the given character
/x
str =~ r
#=> 0
$~.end(0)-1
#=> 10

对于最后一行,我们可以改为写

Regexp.last_match.end(0)-1

请参阅 Regexp::escape, Regexp::last_match 和 MatchData#end。

正则表达式通常编写(即,不是自由间距模式(,编写如下。

/A(?:.*?#{chr_esc}){#{n-1}}.*?#{chr_esc}/

将字符转换为偏移量,删除不匹配字符的偏移量,并返回剩余字符的第n个偏移量

str.size.times.select { |i| str[i] == chr }[n-1]
#=> 10
n = 20
str.size.times.select { |i| str[i] == chr }[n-1]
#=> nil

重复使用字符串#索引来斩首子字符串

s = str.dup
n.times.reduce(0) do |off,_| 
i = s.index(chr)
break nil if i.nil?
s = s[i+1..-1]      
off + i + 1
end - 1
#=> 10

最新更新