"foo bar"f
String#freeze
Преди:
"larodi"f.object_id # => 70328402714000
"larodi"f.object_id # => 70328402714000
"larodi".freeze.object_id # => 70366570584360
"larodi".freeze.object_id # => 70366570566320
Сега:
"larodi"f.object_id # SyntaxError
"larodi".freeze.object_id # => 70321298740820
"larodi".freeze.object_id # => 70321298740820
Exception#cause
$!
се пази последното хвърлено изключение
cause
със стойността на $!
Upgrade NAO!
Regexp
(
, )
, [
, ]
, {
, }
, .
, ?
, +
, *
, ^
, $
, \
, ...
\
/foobar/
или %r(/some/path)
%()
или да има модификатор: %q()
Бърз пример за създаване на низове:
%{foobar} # "foobar"
%(larodi, something "quoted") # "larodi, something \"quoted\""
%(Interpolation? #{'Why, yes!'.upcase}) # "Interpolation? WHY, YES!"
%?foo?
, %~bar~
\n
"
или '
(
и )
%(Parens: ( or ) - works.) # "Parens: ( or ) - works."
%<Parens: < or > - works.> # "Parens: < or > - works."
%[Parens: [ or ] - works.] # "Parens: [ or ] - works."
%{Parens: { or } - works.} # "Parens: { or } - works."
Още един начин за дефиниране на низове, удобен за по-дълги и многоредови текстове:
template = <<HTML
<html>
<head>
<title>K-pop</title>
</head>
<body>
Sparkly
</body>
</html>
HTML
<<-
query = <<-SQL
DROP VIEW ...;
CREATE VIEW ...
SQL
Забележка: Идентацията на текста си остава.
Могат да се вмъкват в нормален код:
scream = <<TEXT.strip.upcase
This is a garrage, don't park! I'll slash your tires and scratch your paint.
TEXT
# => "THIS IS A GARRAGE, DON'T PARK! I'LL SLASH YOUR TIRES AND SCRATCH YOUR PAINT."
Или така:
strings = [<<END, 'second', 'third']
First string
END
# => ["First string\n", "second", "third"]
Дори това работи:
string = [<<ONE, <<TWO, <<THREE]
the first thing
ONE
the second thing
TWO
and the third thing
THREE
# => [" the first thing\n", " the second thing\n", " and the third thing\n"]
Модификатор | Значение |
---|---|
%q( ) | Низ с единични кавички (без интерполация) |
%Q( ) | Низ с двойни кавички (с интерполация) |
%r( ) | Регулярен израз с интерполация; флаговете се слагат след затварящия ограничител |
%i( ) | Списък от символи без интерполация (Ruby 2.0+) |
%I( ) | Списък от символи с интерполация (Ruby 2.0+) |
%w( ) | Списък от думи без интерполация |
%W( ) | Списък от думи с интерполация |
%x( ) | Shell-команда с интерполация |
Сега разбирате защо работи това:
if %r(^(/\w+)*/(?<basename>\w+)) =~ '/some/path/here'
basename # "here"
end
Между другото, регулярните изрази поддържат интерполация по подразбиране:
name = /[^@]+/
host = /\w+\.(com|net|org)/
email = /#{name}@#{host}/ # /(?-mix:[^@]+)@(?-mix:\w+\.(com|net|org))/
[abcd0-9]
, \d
, /[^\d\sA-F]/
, [[:alnum]]
, \p{Cyrillic}
, ...
*
, +
, ?
, {m,n}
?
след повторителя: \w*?
/(\d{4})-(\d\d)/
или /(?\d{4})/
\1
за първата група, \2
за втората, \12
за 12-тата група и прочее
\k<group_identifier>
, където group_identifier
е число или име на група
/(?<word>\w+), \k<word>/
\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) # #<MatchData "(car (car (car (car list))))" 1:"(car (car (car (car list))))" 2:"list)))">
validator.match(invalid) # nil
Да се напише кратък Ruby expression, който проверява дали дадено число е просто или не, посредством употреба на регулярен израз. Резултатът от изпълнението му трябва да еtrue
за прости числа иfalse
за всички останали. Неща, които можете да ползвате:
- Самото число, разбира се.
- Произволни методи от класа
Regexp
- Подходящ регулярен израз (шаблон)
- Текстовия низ
'1'
.String#*
.- Някакъв условен оператор (например
if
-else
или? … : …
)true
,false
, ...
'1' * числото =~ /някакъв регулярен израз/ ? false : true
'1' * 13 =~ /^1?$|^(11+?)\1+$/ ? false : true
/(?=pattern)/
/(?!pattern)/
/(?<=pattern)/
/(?<!pattern)/
/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>") # #<MatchData "bold">
Regexp#match
$~
Regexp.last_match
Enumerable
MatchData#[група]
, където група
е номер или име на група, ви връща порцията текст, отговаряща на съответната група
MatchData#begin(група)
пък ви връща число — отместването спрямо началото на низа на порцията текст, отговаряща на съответната група
/(\w+)/.match('Some words')[1] # "Some"
/(\w+)/.match('Some words').begin(1) # 0
/(?<id>\d+)/.match('ID: 12345')[:id] # "12345"
/(?<id>\d+)/.match('ID: 12345').begin(:id) # 4
MatchData#pre_match
(същото като специалната променлива $`
) — текстът преди съвпадението
MatchData#post_match
(същото като специалната променлива $'
) — текстът след съвпадението
match = /(?<number>\d+)/.match 'ID: 12345 (new)'
match[:number] # "12345"
match.pre_match # "ID: "
match.post_match # " (new)"
$~
, $'
, $1
, $2
, $3
и прочее
match
Regexp#match
html = '<h1>Header</h1>' # или:
html = '<img src="http://my/image.src" alt="Kartman Makes Burgers" />'
case html
when /(<h(\d)>)(.+)<\/h\2>/
{header: $3, size: $2}
when /<a\s+href="([^"]+)">([^<]+)<\/a>/
{url: $1, text: $2}
when /<img\s+src="([^"]+)"\s+alt="([^"]+)"\s*\/>/
{image: $1, alt: $2}
else
'unrecognized tag'
end
# {:image=>"http://my/image.src", :alt=>"Kartman Makes Burgers"}
String#match
String#=~
и String#!=
String#sub
, String#gsub
и вариантите им с !
String#[]
и String#slice
- в някои от вариантите си приемат регулярен израз
String#index
и rindex
приемат и регулярен израз
String#partition
и rpartition
и други...'SomeTitleCase'.gsub /(^|[[:lower:]])([[:upper:]])/ do
[$1, $2.downcase].reject(&:empty?).join('_')
end
# "some_title_case"
Цитат от документацията:
A regexp can be matched against a string when they either share an encoding, or the regexp’s encoding is US-ASCII and the string’s encoding is ASCII-compatible.
Regexp#encoding
/something/u
за UTF-8
Rubyのお父さんはまつもとゆきひろさんです。
unicode_test = 'Rubyのお父さんはまつもとゆきひろさんです。'
/は[[:alpha:]]+さん/.match unicode_test # #<MatchData "はまつもとゆきひろさん">
\b
в Unicode-текст работи, когато границата на думата е лесно определима
/\b[[:alpha:]]\b/.match 'това и онова' # #<MatchData "и">
Rubyのお父さんはまつもとゆきひろさんです。
?Например:
'Ruby no otousan ha Matsumoto Yukihiro san desu.'.gsub(/(\b[[:alpha:]]+\b)/) { "[#{$1}]" }
# "[Ruby] [no] [otousan] [ha] [Matsumoto] [Yukihiro] [san] [desu]."
Но:
'Rubyのお父さんはまつもとゆきひろさんです。'.gsub(/(\b[[:alpha:]]+\b)/) { "[#{$1}]" }
# "[Rubyのお父さんはまつもとゆきひろさんです]。"
/pattern/flags
i
прави търсенето на съвпадение нечувствително към регистъра на буквите
u
кара шаблона да носи задължителна кодировка UTF-8
m
превръща шаблона в multiline-такъв (в този режим, например, .
ще съвпада и с нов ред)
(?(cond)yes|no)
cond
може да е референция към друга група в шаблона, или пък look-ahead/behind
regexp = /^([A-Z])?[a-z]+(?(1)[A-Z]|[a-z])$/
regexp =~ "foo" # 0
regexp =~ "foO" # nil
regexp =~ "FoO" # 0
Regexp
: http://www.ruby-doc.org/core-2.1.0/Regexp.html
MatchData
: http://www.ruby-doc.org/core-2.1.0/MatchData.html
String
: http://www.ruby-doc.org/core-2.1.0/String.html
ri
, например: ri Regexp#=~
RE: <моят въпрос>
, той ще го Google-не вместо вас и ще ви върне отговор в body-то на email-аЗа предпочитане по темата за регулярните изрази.
Примерното решение, което даваме, е на Петко:
class String
def longest_sequence
return [] if empty?
scan(/(.)(\1*)/).map(&:join).group_by(&:length).max.last.map(&:chr).uniq
end
end
Да ги разгледаме.