Ruby Language
Wyrażenia regularne i operacje na podstawie wyrażeń regularnych
Szukaj…
Grupy nazwane i inne.
Ruby rozszerza standardową składnię grupy (...)
o nazwaną grupę (?<name>...)
. Pozwala to na ekstrakcję według nazwy zamiast liczyć, ile masz grup.
name_reg = /h(i|ello), my name is (?<name>.*)/i #i means case insensitive
name_input = "Hi, my name is Zaphod Beeblebrox"
match_data = name_reg.match(name_input) #returns either a MatchData object or nil
match_data = name_input.match(name_reg) #works either way
if match_data.nil? #Always check for nil! Common error.
puts "No match"
else
match[0] #=> "Hi, my name is Zaphod Beeblebrox"
match[1] #=> "i" #the first group, (i|ello)
match[2] #=> "Zaphod Beeblebrox"
#Because it was a named group, we can get it by name
match[:name] #=> "Zaphod Beeblebrox"
match["name"] #=> "Zaphod Beeblebrox"
puts "Hello #{match[:name]}!"
end
Indeks dopasowania jest liczony na podstawie kolejności lewych nawiasów (przy czym cała regex jest pierwszą grupą o indeksie 0)
reg = /(((a)b)c)(d)/
match = reg.match 'abcd'
match[0] #=> "abcd"
match[1] #=> "abc"
match[2] #=> "ab"
match[3] #=> "a"
match[4] #=> "d"
= ~ operator
if /hay/ =~ 'haystack'
puts "There is hay in the word haystack"
end
Uwaga: kolejność jest znacząca . Chociaż 'haystack' =~ /hay/
jest w większości przypadków równoważny, skutki uboczne mogą się różnić:
- Ciągi przechwycone z nazwanych grup przechwytywania są przypisywane do zmiennych lokalnych tylko wtedy, gdy wywoływane jest
regexp =~ str
Regexp#=~
(regexp =~ str
); - Ponieważ właściwym operandem może być dowolny obiekt, dla
regexp =~ str
zostanie nazwanyregexp =~ str
Regexp#=~
lubString#=~
.
Zauważ, że to nie zwraca wartości prawda / fałsz, zamiast tego zwraca indeks dopasowania, jeśli został znaleziony, lub zero, jeśli nie został znaleziony. Ponieważ wszystkie liczby całkowite w rubinie są prawdziwe (w tym 0), a zero jest fałszem, działa to. Jeśli chcesz wartość logiczną, użyj #===
jak pokazano w innym przykładzie .
Kwantyfikatory
Kwantyfikatory pozwalają określić liczbę powtarzanych ciągów.
Zero lub jeden:
/a?/
Zero lub wiele:
/a*/
Jeden lub wiele:
/a+/
Dokładny numer:
/a{2,4}/ # Two, three or four /a{2,}/ # Two or more /a{,4}/ # Less than four (including zero)
Domyślnie kwantyfikatory są zachłanne , co oznacza, że biorą tyle znaków, ile mogą, jednocześnie dopasowując. Zwykle nie jest to zauważalne:
/(?<site>.*) Stack Exchange/ =~ 'Motor Vehicle Maintenance & Repair Stack Exchange'
Nazwana site
grupy przechwytywania zostanie ustawiona zgodnie z oczekiwaniami na „Konserwacja i naprawa pojazdów silnikowych”. Ale jeśli „Wymiana stosu” jest opcjonalną częścią ciągu (ponieważ może to być zamiast tego „Przepełnienie stosu”), naiwne rozwiązanie nie będzie działać zgodnie z oczekiwaniami:
/(?<site>.*)( Stack Exchange)?/
Ta wersja nadal będzie pasować, ale nazwane przechwytywanie będzie zawierać „Stack Exchange”, ponieważ *
łapczywie zjada te postacie. Rozwiązaniem jest dodanie kolejnego znaku zapytania, aby *
leniwy:
/(?<site>.*?)( Stack Exchange)?/
Dołączasz ?
do dowolnego kwantyfikatora sprawi, że będzie leniwy.
Klasy postaci
Opisuje zakresy symboli
Możesz wyliczyć symbole jawnie
/[abc]/ # 'a' or 'b' or 'c'
Lub użyj zakresów
/[a-z]/ # from 'a' to 'z'
Możliwe jest łączenie zakresów i pojedynczych symboli
/[a-cz]/ # 'a' or 'b' or 'c' or 'z'
Wiodący myślnik ( -
) jest traktowany jako charachter
/[-a-c]/ # '-' or 'a' or 'b' or 'c'
Klasy mogą być ujemne, gdy poprzedzają symbole ^
/[^a-c]/ # Not 'a', 'b' or 'c'
Istnieją skróty do popularnych klas i specjalnych postaci, a także zakończenia linii
^ # Start of line
$ # End of line
\A # Start of string
\Z # End of string, excluding any new line at the end of string
\z # End of string
. # Any single character
\s # Any whitespace character
\S # Any non-whitespace character
\d # Any digit
\D # Any non-digit
\w # Any word character (letter, number, underscore)
\W # Any non-word character
\b # Any word boundary
\n
będzie rozumiany po prostu jako nowa linia
Aby uciec od dowolnego zarezerwowanego znaku, takiego jak /
lub []
a inni używają odwrotnego ukośnika (lewy ukośnik)
\\ # => \
\[\] # => []
Wyrażenia regularne w instrukcjach przypadków
Możesz sprawdzić, czy łańcuch pasuje do kilku wyrażeń regularnych, używając instrukcji switch.
Przykład
case "Ruby is #1!"
when /\APython/
puts "Boooo."
when /\ARuby/
puts "You are right."
else
puts "Sorry, I didn't understand that."
end
Działa to, ponieważ instrukcje case są sprawdzane pod kątem równości przy użyciu operatora ===
, a nie operatora ==
. Kiedy wyrażenie regularne znajduje się po lewej stronie porównania za pomocą ===
, przetestuje ciąg, aby sprawdzić, czy pasuje.
Definiowanie Regexp
Regexp można utworzyć w Ruby na trzy różne sposoby.
używając ukośników:
/ /
używając
%r{}
using
Regex.new
#The following forms are equivalent regexp_slash = /hello/ regexp_bracket = %r{hello} regexp_new = Regexp.new('hello') string_to_match = "hello world!" #All of these will return a truthy value string_to_match =~ regexp_slash # => 0 string_to_match =~ regexp_bracket # => 0 string_to_match =~ regexp_new # => 0
mecz? - Wynik logiczny
Zwraca true
lub false
, co wskazuje, czy wyrażenie regularne jest dopasowane, czy nie bez aktualizacji $~
i innych powiązanych zmiennych. Jeśli obecny jest drugi parametr, określa on pozycję w ciągu, aby rozpocząć wyszukiwanie.
/R.../.match?("Ruby") #=> true
/R.../.match?("Ruby", 1) #=> false
/P.../.match?("Ruby") #=> false
Ruby 2.4+
Wspólne szybkie użycie
Wyrażenia regularne są często używane w metodach jako parametry do sprawdzania, czy obecne są inne ciągi lub do wyszukiwania i / lub zastępowania ciągów.
Często zobaczysz następujące informacje:
string = "My not so long string"
string[/so/] # gives so
string[/present/] # gives nil
string[/present/].nil? # gives true
Możesz więc użyć tego po prostu do sprawdzenia, czy łańcuch zawiera podłańcuch
puts "found" if string[/so/]
Bardziej zaawansowane, ale wciąż krótkie i szybkie: wyszukaj określoną grupę za pomocą drugiego parametru, w tym przykładzie drugim jest drugi, ponieważ numeracja zaczyna się od 1, a nie od 0, grupa jest zawarta w nawiasach.
string[/(n.t).+(l.ng)/, 2] # gives long
Często używane również: wyszukaj i zamień na sub
lub gsub
, \1
daje pierwszą znalezioną grupę, \2
drugą:
string.gsub(/(n.t).+(l.ng)/, '\1 very \2') # My not very long string
Ostatni wynik zostaje zapamiętany i można go użyć w następujących wierszach
$2 # gives long