Wait, forgot to escape a space. Wheeeeee[taptaptap]eeeeee.
Имаме следната задача:
Да се напише кратък Ruby expression, който проверява дали дадено число е просто или не, посредством употреба на регулярен израз. Резултатът от изпълнението му трябва да еtrue
за прости числа иfalse
за всички останали. Неща, които можете да ползвате:
- Самото число, разбира се.
- Произволни методи от класа
Regexp
- Подходящ регулярен израз (шаблон)
- Текстовия низ
'1'
.String#*
.- Някакъв условен оператор (например
if
-else
или? … : …
)true
,false
, ...
Имаме следната задача:
Да валидирате изрази от следния тип за правилно отворени/затворени скоби:
(car (car (car ...)))
- Например:
(car (car (car (car list))))
- Целта е израз, чийто резултат да може да се ползва в условен оператор (
true
/false
-еквивалент)- Можете да ползвате произволни методи от класа
Regexp
- И регулярен израз, разбира се
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
strace
— плюсове и минуси
SIGABRT
Текстуално илюстриране на света и змията:
.................................................. .................................................. ..................##@@............................ ..................##.............................. ..................######.......................... .................................................. ..................................................
rails_autolink
grep
, sed
, awk
, vi
, Emacs
...
Regexp
/pattern/
%r
, например: %r{/path/maching/made/easy}
Regexp
String
също има методи за работа с регулярни изразиRegexp#match
nil
, ако шаблонът не "хваща" нищо
MatchData
, ако шаблонът "хваща" нещо от низа
MatchData
в детайли — по-късно
/wool/
ще отговаря на точно тази последователност от символи в низ
(
, )
, [
, ]
, {
, }
, .
, ?
, +
, *
, ^
, $
, \
, ...
-
)/find me/.match 'Can you find me here?' # #<MatchData "find me">
/find me/.match 'You will not find ME!' # nil
.
съвпада с един произволен символ (с изключение на символите за нов ред)
[
и ]
се ползват за дефиниране на класове от символи
*
, ?
, +
, {
и }
се ползват за указване на повторения
^
, $
, \b
, \B
и т.н. са "котви" и съответстват на определени "междусимволни дупки" :)
|
има смисъл на "или", например:/day|nice/.match 'A nice dance-day.' # #<MatchData "nice">
/da(y|n)ce/.match 'A nice dance-day.' # #<MatchData "dance" 1:"n">
Внимавайте с приоритета на |
\
пред специален символ го прави неспециален такъв (екранира го)
\\
(като в обикновен низ)[
и ]
[a-z]
или [0-9A-F]
^
, това означава "някой символ, който не е посочен в класа"
[a\-b]
[-abc]
или [abc-]
- тук то няма специален смисъл
/W[aeiou]rd/.match "Word" # #<MatchData "Word">
/[0-9a-f]/.match '9f' # #<MatchData "9">
/[9f]/.match '9f' # #<MatchData "9">
/[^a-z]/.match '9f' # #<MatchData "9">
\w
- символ от дума ([a-zA-Z0-9_]
)
\W
- символ, който не може да участва в дума ([^a-zA-Z0-9_]
)
\d
- цифра ([0-9])
\D
- символ, който не е цифра ([^0-9]
)
\h
- шеснадесетична цифра ([0-9a-fA-F]
)
\H
- символ, който не е шеснадесетична цифра ([^0-9a-fA-F]
)
\s
- whitespace-символ (/[ \t\r\n\f]/
)
\S
- символ, който не е whitespace (/[^ \t\r\n\f]/
)[[:alpha:]]
- символ от азбука
[[:alnum:]]
- горното или цифра
[[:blank:]]
- интервал или таб
[[:cntrl:]]
- контролен символ
[[:digit:]]
- цифра
[[:lower:]]
- малка буква
[[:upper:]]
- главна буква
[[:print:]]
- printable-символ
[[:punct:]]
- пунктуационен символ
[[:space:]]
- whitespace-символ (вкл. и нов ред)
[[:xdigit:]]
- шеснадеситична цифра
[[:word:]]
- символ, който може да участва в дума (работи и за Unicode, за разлика от \w
)
[[:ascii:]]
- ASCII-символ\p{}
може да match-вате символи, имащи определено свойство (подобно на POSIX)
\p{Alnum}
, \p{Alpha}
, \p{Blank}
, \p{Cntrl}
, \p{Digit}
, \p{Graph}
\p{Katakana}
\p{Cyrillic}
, например:/\s\p{Cyrillic}\p{Cyrillic}\p{Cyrillic}/.match 'Ние сме на всеки километър!' # #<MatchData " сме">
^
съвпада с началото на ред (Ruby е в multiline режим по подразбиране)
$
съвпада с края на ред
\A
съвпада с началото на текстов низ
\z
съвпада с края на низ
\b
отговаря на граница на дума (когато е извън [
и ]
; вътре означава backspace
)
\B
отговаря на място, което не е граница на дума/real/.match "surrealist" # #<MatchData "real">
/\Areal/.match "surrealist" # nil
/\band/.match "Demand" # nil
/\Band.+/.match "Supply and demand curve" # #<MatchData "and curve">
s
s*
означава нула или повече повторения на s
s+
търси едно или повече повторения на s
s?
съвпада с нула или едно повторение на s
s{m,n}
означава между m и n повторения на s
m
или n
:
s{,n}
има смисъл на нула до n
повторения, а s{m,}
— поне m
повторения
s{n}
означава точно n
повторения/e+/.match 'Keeewl' # #<MatchData "eee">
/[Kke]+/.match 'Keeewl' # #<MatchData "Keee">
/\w+/.match '2038 - the year' # #<MatchData "2038">
/".*"/.match '"Quoted text!"' # #<MatchData "\"Quoted text!\"">
/[[:upper:]]+[[:lower:]]+l{2}o/.match 'Hello' # #<MatchData "Hello">
?
след повторителя
.*?
кара повторителя *
да се държи не-лакомо
/<.+>/.match("<a><b>") # #<MatchData "<a><b>">
/<.+?>/.match("<a><b>") # #<MatchData "<a>">
Символите (
и )
се използват за логическо групиране на части от шаблона с цел:
day
или dance
: /\bda(y|nce)\b/
Текстът, който match-ва частта на шаблона, оградена в скоби, може да се достъпва:
\1
за първата група, \2
за втората и т.н.
MatchData
-обекта
$1
, $2
... за номерирани групи
date_string = '2012-11-12'
date_parts = /\A(\d{4})-(\d\d)-(\d\d)\z/.match(date_string)
if date_parts
Date.new date_parts[1].to_i, date_parts[2].to_i, date_parts[3].to_i
# #<Date: 2012-11-12 ...>
end
=~
и !~
— дефинирани в Regexp
и в String
/pattern/ =~ 'Some string'
'Some string' =~ /pattern/
nil
, ако няма съвпадение, или число (offset), ако има такова
$1
, $~
...)
if
log_entry = "[2011-07-22 15:42:12] - GET / HTTP/1.1 200 OK"
if log_entry =~ /\bHTTP\/1\.1 (\d+)/
request_status = $1.to_i # 200
else
raise "Malformed log entry!"
end
date_string = '2012-11-12'
if date_string =~ /\A(\d{4})-(\d\d)-(\d\d)\z/
Date.new $1.to_i, $2.to_i, $3.to_i # #<Date: 2012-11-12 ...>
end
(?<name>)
или така: (?'name')
, където name
е името на групата
(?<date>\d{4}-\d{2}-\d{2})
/(?<date>\d{4}-\d{2}-\d{2})/.match 'Today is 2011-11-08, Tuesday.' # #<MatchData "2011-11-08" date:"2011-11-08">
\1
, \2
и прочее, ако групите ви не са именовани
\11
се обръща към 11-тата група
\1
, последван от символа 1
"?
\k<group_identifier>
, където group_identifier
е число или име на група
/(?<word>\w+), \k<word>/
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/.match 'Today is 2011-11-08, Tuesday.'
# #<MatchData "2011-11-08" year:"2011" month:"11" day:"08">
/(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\11/.match 'Regular expressions'
# #<MatchData "ular express" 1:"u" 2:"l" 3:"a" 4:"r" 5:" " 6:"e" 7:"x" 8:"p" 9:"r" 10:"e" 11:"s">
/(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\k<11>1/.match 'Regular express1ions'
# #<MatchData "ular express1" 1:"u" 2:"l" 3:"a" 4:"r" 5:" " 6:"e" 7:"x" 8:"p" 9:"r" 10:"e" 11:"s">
/(\w+), \1/.match 'testing, testing' # #<MatchData "testing, testing" 1:"testing">
/(\w+), \1/.match 'testing, twice' # nil
/(?<word>\w+), \k<word>/.match 'testing, testing' # #<MatchData "testing, testing" word:"testing">
/".*"/.match '"Quoted"' # #<MatchData "\"Quoted\"">
Частта от шаблона .*
хваща Quoted"
, тъй като е алчна. Това води до невъзможност да се намери съвпадение и алгоритъмът backtrack-ва -- връща се една стъпка/символ назад.
(?>pattern)
/"(?>.*)"/.match('"Quote"') # nil
\g<name>
, където name
е номер или име на група в шаблона
/(\w+), \1/.match 'testing, twice' # nil
/(\w+), \g<1>/.match 'testing, twice' # #<MatchData "testing, twice" 1:"twice">
Да валидирате изрази от следния тип за правилно отворени/затворени скоби:
(car (car (car ...)))
- Например:
(car (car (car (car list))))
- Целта е израз, чийто резултат да може да се ползва в условен оператор (
true
/false
-еквивалент)- Можете да ползвате произволни методи от класа
Regexp
- И регулярен израз, разбира се
validator = /^(\(car (\g<1>*|\w*)\))$/
valid = '(car (car (car (car list))))'
invalid = '(car (car (car list))'
validator.match(valid) ? true : false # true
validator.match(invalid) ? true : false # false
Следващата седмица ще довършим темата за регулярните изрази.