re = /\A # Begin at the beginning only! (No doing it again)
(?: # Non-capturing group consuming the string
(?| # Branch reset on two groups: p2 and p3 (p for prefix)
. # Consume a character
(?=.*+\n(?<p2>\k<p2>?+.) # Lookahead: Go to next line. Then add a character to a group
.*+\n(?<p3>\k<p3>?+.)) # Same. Will fail if the line is too short.
| # When the first brach fails:
.*+\n(?<p2>)(?<p3>) # Consume the rest of the string. Reset the groups.
)+? # As little as possible (Only one character at a time)
(?<=X)(?=.*\n\k<p2>(?<=X).*\n\k<p3>(?<=X)) # Check to see if there's a column of X's
(?=[\s\S]*(?<count>[\s\S](?(<count>)\k<count>))) # Add a character to a count group at the end.
)+ # Keep doing it until all is consumed/mx
str = 'XX
XX
XX
X
X
X'
# Print the match result
str.scan(re) do |match|
puts match.to_s
end
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for Ruby, please visit: http://ruby-doc.org/core-2.2.0/Regexp.html