如何搜索两个或多个空白和指针ruby



我正在尝试读取一个.txt文件,在每行中搜索两个或多个空白,并使用stringScanner gem 将指针保存在匹配的位置

到目前为止,我已经设法找到了匹配,但我不知道如何保存指针

require 'strscan'
class LintFile
attr_reader :file, :lines
def initialize(filepath)
@file = File.open(filepath)
@lines = []
end
def read
# Here I get each line into an array
@file.each_with_index do |line, ind|
@lines[ind] = StringScanner.new(line)
end
end
end
def check_error(filepath)
@file_to_check = LintFile.new(filepath)
@file_to_check.read
#file_to_check.lines

#Scan each line
@file_to_check.lines.length.times do |line|
whitespace(line)
end
end
def whitespace(line)
if @file_to_check.lines[line].string.match?("  ")
#pos is not giving the pointer where the match occurred
pointer = @file_to_check.lines[line].pos
puts "Estoy dentro del unless #{pointer}"
end
end

请帮帮我!

提前感谢

假设文件包含一个字符串,该字符串被读入变量str。例如:

str =<<~_
Now is  the time for
all good Rubyists to
come    to the    aid
of their fellow    coders.
_

使用StringScanner方法

我们可以如下获得由两个或多个空间组成的每个子串的开头到串str的偏移。如图所示,获得每行的偏移量(而不是str(是对我将描述的计算的直接修改。

require 'strscan'
def scan_it(str)    
s = StringScanner.new(str)
arr = []
until s.eos?
ss = s.scan(/ {2,}/)
if ss
arr << s.pos - ss.size
else
s.scan(/ ?[^ ]+/)
end
end
arr
end

我们获得:

arr = scan_it(str)
#=> [6, 46, 56, 79] 

让我们检查str中那些偏移量周围的子字符串。

arr.map { |n| puts str[n-3,10] }
is  the t
ome    to 
the    aid
low    cod

正则表达式/ {2,}/匹配两个或多个空格。正则表达式/ ?[^ ]+/匹配除空格([^ ](之外的一个或多个(+(字符,可选地在其前面加一个空格(?(。

s.scan的匹配项如下表所示。(第一列中的下划线表示空格。(

ss        regex matched    s.pos  s.pos-ss.size            
-----------------------------------------------            
Now          / ?[^ ]+/        3          
_is          / ?[^ ]+/        6
__           / {2,}/          8         6
the          / ?[^ ]+/       11 
_time        / ?[^ ]+/       16 
_fornall    / ?[^ ]+/       24
_good        / ?[^ ]+/       29
_Rubyists    / ?[^ ]+/       38
_toncome    / ?[^ ]+/       46
____         / {2,}/         50        46
to           / ?[^ ]+/       52
_the         / ?[^ ]+/       56  
____         / {2,}/         60        56
aidnof      / ?[^ ]+/       66
_their       / ?[^ ]+/       72
_fellow      / ?[^ ]+/       79
____         / {2,}/         83        79
coders.      / ?[^ ]+/       90      

获取每条线的偏移

str.each_line.with_index.with_object({}) do |(line,i),h|
h[i] = scan_it(line)
end
#=> {0=>[6], 1=>[], 2=>[4, 14], 3=>[15]}

这表明在第一行(行偏移0(中有两个或多个空格的一个子串,从偏移6开始,在第二行中没有子串,在第三行中有两个子串,在偏移414开始,在最后一行中有一子串,从偏置15开始。

请参阅字符串#each_line、枚举器#with_index和枚举器#with_object。

使用字符串#gsub

这里有一种不使用StringScanner的计算所需偏移的更简单方法。

str.gsub(/ {2,}/).map { |_,arr| Regexp.last_match.begin(0) }
#=> [6, 46, 56, 79]

这使用了String#gsub的形式,它只接受一个参数(模式(而不接受块。这返回一个枚举器,该枚举器仅生成匹配项(每个匹配项由两个或多个空格组成的字符串(,并且不执行替换(使名称gsub有些混乱(。我已将枚举器链接到Enumerable#映射。

每个匹配都由第一个块变量保持。我为该变量使用了下划线,以向读者表明它没有用于块计算(这是一种常见的做法(。

另请参阅Regexp::last_match,它返回一个MatchData对象,以及MatchData#begin,它为我们提供了当前匹配开始的偏移量。

获取两个或多个空间的子字符串的行内的行和位置开始

str.each_line.with_index.with_object({}) do |(line,i),h|
h[i] = line.gsub(/ {2,}/).map { |_,arr| Regexp.last_match.begin(0) }
end
#=> {0=>[6], 1=>[], 2=>[4, 14], 3=>[15]}

最新更新