регулярное выражение aa, bb, cc - PullRequest
5 голосов
/ 11 июля 2019

Я ожидал, что будет работать следующее (и оно работает):

x = '"aa","bb","cc"'

x =~ /\A(".*?",){2}".*?"\Z/
#=> 0 

... но я не ожидал, что следующие два сработают (и не хочу, чтобы они работали). Я специально использовал ?, чтобы сделать .* нежадным:

x =~ /\A(".*?",){0}".*?"\Z/
#=> 0 

x =~ /\A(".*?",){1}".*?"\Z/
#=> 0 

Я ожидаю: начало строки (\A), затем "aa",, затем "bb", (сейчас два совпадения, то есть {2}), затем "cc" и конец строки \Z.

Я понимаю , почему они работают, но я хочу понять, как добиться того, чего я хочу ...

Я хочу, чтобы не удалось в последних двух примерах выше (но это не так). Другими словами, я хочу, чтобы следующее не получилось:

x = '"aa","bb","cc","dd"'

x =~ /\A(".*?",){2}".*?"\Z/
#=> 0 

Он должен видеть: \A, "aa", "bb", "cc" и затем FAIL на последующем , (тот факт, что это не было \Z).

1 Ответ

6 голосов
/ 11 июля 2019

Проблема в том, что . является слишком общим, и что даже не жадный .*? будет соответствовать , или ":

'"aa","bb","cc"'.match(/\A(".*?",){1}(".*?")\Z/).captures
#=> ["\"aa\",", "\"bb\",\"cc\""]

Кроме того, нет разницы между жадным и не жадным совпадением, если им обоим нужно продолжать до конца строки. /.*\Z/ совпадает с /.*?\Z/.

Вы не можете удалить \Z, поэтому вы можете заменить . на [^"], чтобы избежать совпадения ".

three = '"aa","bb","cc"'
four = '"aa","bb","cc","dd"'

pattern = /\A("[^"]*",){2}"[^"]*"\Z/

(three =~ pattern) && (four !~ pattern)
#=> true

regex on debuggex

Если регулярное выражение становится слишком нечитаемым, альтернативой может быть попытка проанализировать ваш текст как массив JSON:

require 'json'
three = '"aa","bb","cc"'
four = '"aa","bb","cc","dd"'

def has_n_strings?(text, n)
  words = JSON.parse("[#{text}]")
  words.all?(String) && words.size == n
end

puts has_n_strings?(three, 3)
# true
puts has_n_strings?(three, 4)
# false
puts has_n_strings?(four, 4)
# true
puts has_n_strings?(four, 3)
# false
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...