#regex #ruby
#регулярное выражение #ruby
Вопрос:
Я написал регулярное выражение на ruby, которое отлично работает в одной строке, но оно довольно большое, поэтому мне нужно записать его в многострочной форме.
Я использую %r{}x
формат для его использования в многострочном режиме, но он не работает.
regex = (/A(RM|R1)([A-Z])([A-Z])(d )(dd )([A-Z])([A-Z])([A-Z] )-?(d )([A-Z])(d)#?([A-Z])([A-Z])(d)z/)
в одной строке
regex = %r{
([A-Z])
([A-Z])
([A-Z])
(d )
(dd )
([A-Z])
([A-Z])
([A-Z] )
-?
(d )
([A-Z])
(d)
#?
([A-Z])
([A-Z])
(d)
}x
в нескольких строках (по одной группе в каждой строке)
Что не так с моим подходом?
Ответ №1:
Вы должны экранировать #
символ, как в режиме свободного пробела, он обозначает начало комментария:
Буквенный пробел внутри шаблона игнорируется, а символ octothorpe (
#
) вводит комментарий до конца строки. Это позволяет организовать компоненты шаблона потенциально более удобным для чтения способом.
Итак, замените #?
на #?
.
Ответ №2:
Вот ваше регулярное выражение, определенное в режиме свободного пробела, и это то, что, я думаю, вы ищете.
regex = /
A # beginning of string
(RM|R1) # match 'RM' or 'R1' CG 1
([A-Z]) # match 1 uppercase letter CG 2
([A-Z]) # match 1 uppercase letter CG 3
(d ) # match > 0 digits CG 4
(d{2,}) # match > 0 digits CG 5
([A-Z]) # match 1 uppercase letter CG 6
([A-Z]) # match 1 uppercase letter CG 7
([A-Z] ) # match > 0 uppercase letters CG 8
-? # optionally match '-'
(d ) # match > 0 digits CG 9
([A-Z]) # match 1 uppercase letter CG 10
(d) # match > 0 digits CG 11
#? # optionally match '#'
([A-Z]) # match 1 uppercase letter CG 12
([A-Z]) # match 1 uppercase letter CG 13
(d) # match > 0 digits CG 14
z # end of string
/x # free-spacing regex definition mode
«CG» означает «группу захвата». Одним из основных применений режима свободного интервала является документирование регулярного выражения, как я сделал здесь .
Я внес два изменения в ваше регулярное выражение. Во-первых, я заменил (dd )
на (d{2,})
, который имеет тот же эффект, но, возможно, читается лучше. Во-вторых, символ "#"
начинает комментарий в режиме свободного интервала, поэтому он должен быть экранирован ( #
), если он должен быть сопоставлен.
В качестве примера использования этого регулярного выражения,
test_str = "RMAB12345CDEF-6G7#HI8"
m = test_str.match regex
#=> #<MatchData "RMAB12345CDEF-6G7#HI8" 1:"RM" 2:"A" 3:"B" 4:"123" 5:"45"
# 6:"C" 7:"D" 8:"EF" 9:"6" 10:"G" 11:"7" 12:"H" 13:"I" 14:"8">
m.captures
#=> ["RM", "A", "B", "123", "45", "C", "D", "EF", "6", "G", "7", "H", "I", "8"]
Обратите внимание, что неясно, как 5 цифр должны быть разделены между группами захвата 4 и 5.
Есть одна вещь, с которой вы должны быть осторожны при использовании режима свободного пробела. Все пробелы удаляются перед анализом выражения, включая любые пробелы, которые вы хотите сопоставить. Например,
"ab c".match? /ab c/ #=> true
"ab c".match? /ab c/x #=> false
"abc".match? /ab c/x #=> true
Вот несколько способов защитить символ пробела (все возвращаемые true
):
"ab c".match? /ab[ ]c/x # put in a character class
"ab c".match? /ab[[:space:]]c/x # Unicode bracket expression
"ab c".match? /abp{Space}c/x # Unicode p{} construct
"ab c".match? /absc/x # match a whitespace character
Обратите внимание, что s
соответствует табуляции, новой строке и двум другим символам, а также пробелам, которые могут быть или не быть желательными.