17. Regular expressions, част 2

17. Regular expressions, част 2

17. Regular expressions, част 2

10 декември 2014

Проекти

Проекти - точкуване, изисквания, планиране

Основна цел на проектите

Въпрос 1

Каква е рализката между следните?

/(\w+), \g<1>/.match 'something, fishy' # => ?
/(\w+), \1/.match    'something, fishy' # => ?

Въпрос 1

Каква е рализката между следните?

/(\w+), \g<1>/.match 'something, fishy'   # #<MatchData "something, fishy" 1:"fishy">
/(\w+), \1/.match    'something, fishy'   # nil

\1 match-ва match-натото от първата група. \g<1> преизпълнява pattern-а на групата.

Въпрос 2

Какъв ще бъде резултатът?

/(\b\w+\b\s){4}\g<1>/.match 'the right person in the wrong place...'
$1 # => ?

Въпрос 2

Какъв ще бъде резултатът?

/(\b\w+\b\s){4}\g<1>/.match 'the right person in the wrong place...'
$1   # "the "

$1 се променя при всяко ново match-ване на групата. В това число и когато я преизпълните рекурсивно.

Въпрос 3

Къде и колко (не е нужно точно число) ще се backtrack-не:

/.*?hi.*there/.match 'om, nom, nom... oh hi there...'

.*? ще започне от 0 символа и ще увеличава с един за всичко преди hi. .* ще започне с целия низ след hi и ще намаля с един, докато не стигне до началото на there.

Кратък преговор от миналия път

Лятна предприемаческа програма

Summer Entrepreneurship Program

iie.org/Programs/Bulgarian-Young-Leaders-Program/SEP

Какво е това?

Защо искам да отида?

Защо има смисъл да отида?

Как да кандидатствам?

Информационна среща и ресурси

MOAR, MOAR!!!!111!

Проверете дали нещо е валиден математически израз
  • Произволно цяло число 1337
  • Променлива (малка латинска буква) x
  • Знак пред валиден израз (+, -) -33 + 22 * -y
  • Операция между валидни изрази (+, -, *, /) x + y - 21 / 3
  • Скоби, ограждащи валидни изрази -x * (y + -5 * (7 - 13)) / 44 - 9000

Примерно решение

so simple, right?

validator = /^([-+]?(\d+|[a-z]|\(\g<1>\)|\g<1> [-+*\/] \g<1>))$/

valid   = '-(3 + (x * (7 / y))) * (44 * y - z / 22)'
invalid = '((33 - 7) * x'

validator.match(valid)   ? true : false
validator.match(invalid) ? true : false

Примерно решение

nope... fail!

/^([-+]?(\d+|[a-z]|\(\g<1>\)|\g<1> [-+*\/] \g<1>))$/# ~> -:1: never ending recursion: /^([-+]?(\d+|[a-z]|\(\g<1>\)|\g<1> [-+*\/] \g<1>))$/

Примерно решение

с рекурсивни групи

validator = /^([-+]?(\d+|[a-z]|\(\g<1>\))( [-+*\/] \g<1>)?)$/

valid   = '-(3 + (x * (7 / y))) * (44 * y - z / 22)'
invalid = '((33 - 7) * x'

validator.match(valid)   ? true : false # true
validator.match(invalid) ? true : false # false

Look-ahead и look-behind

/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favours the <b>bold</b>") # #<MatchData "bold">

Пример

Сменете * на % ако тя не е екранирана (escape-ната)
  • foo* => foo%
  • foo\* => foo\*
  • foo\\\\* => foo\\\\%
  • *\\\** => %\\\*%

Първи начин

"*\\**".gsub(/((?<!\\)(?:\\\\)*)\*/, '\1%') # "%\\*%"

Втори начин

"*\\**".gsub(/\G([^*\\]*(?:\\.[^*\\]*)*)\*/, '\1%') # "%\\*%"

Интерполация в регулярни изрази

Между другото, регулярните изрази поддържат интерполация по подразбиране:

name      = /[^@]+/
host      = /\w+\.(com|net|org)/

email     = /#{name}@#{host}/ # /(?-mix:[^@]+)@(?-mix:\w+\.(com|net|org))/

Работа с MatchData-обекти

Най-полезни методи на MatchData-обектите

/(\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

#pre_match и #post_match методи

на MatchData-обектите

match = /(?<number>\d+)/.match 'ID: 12345 (new)'

match[:number]    # "12345"
match.pre_match   # "ID: "
match.post_match  # " (new)"

Специалните променливи

case с регулярни изрази

работи благодарение на Regexp#===

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

свързани с регулярни изрази

Пример със String#gsub

плюс групи и блок

'SomeTitleCase'.gsub /(^|[[:lower:]])([[:upper:]])/ do
  [$1, $2.downcase].reject(&:empty?).join('_')
end

# "some_title_case"

Encoding

Цитат от документацията:

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.

Encoding & Unicode

Rubyのお父さんはまつもとゆきひろさんです。
unicode_test = 'Rubyのお父さんはまつもとゆきひろさんです。'

/は[[:alpha:]]+さん/.match unicode_test # #<MatchData "はまつもとゆきひろさん">

Граници на думи в Unicode-текст

Граници на думи в Unicode-текст

пример

Например:

'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のお父さんはまつもとゆきひろさんです]。"

Флагове на шаблоните

Условия в шаблоните (if)

Ново в Ruby 2.0

regexp = /^(number)?\s*(?(1)\d+|[a-zA-Z]+)$/

regexp =~ "number 123"   # 0
regexp =~ "foo"          # 0
regexp =~ "number baz"   # nil

Документация

Валидация на просто число с регулярен израз

Да се напише кратък Ruby expression, който проверява дали дадено число е просто или не, посредством употреба на регулярен израз. Резултатът от изпълнението му трябва да е true за прости числа и false за всички останали. Неща, които можете да ползвате:
  • Самото число, разбира се.
  • Произволни методи от класа Regexp
  • Подходящ регулярен израз (шаблон)
  • Текстовия низ '1'.
  • String#*.
  • Някакъв условен оператор (например if-else или ? … : …)
  • true, false, ...

Решение на проверката за просто число с РИ

Въпроси?

Like any...

Въпроси