Konwertuj ciąg na ruby ​​wyrażenia regularnego

118

Muszę przekonwertować ciąg, taki jak „/ [\ w \ s] + /”, na wyrażenie regularne.

"/[\w\s]+/" => /[\w\s]+/

Próbowałem użyć różnych Regexpmetod, takich jak:

Regexp.new("/[\w\s]+/") => /\/[w ]+\//, podobnie Regexp.compilei Regexp.escape. Ale żaden z nich nie wraca tak, jak się spodziewałem.

Co więcej, próbowałem usunąć ukośniki odwrotne:

Regexp.new("[\w\s]+") => /[w ]+/ Ale nie mam szczęścia.

Potem spróbowałem zrobić to prosto:

str = "[\w\s]+"
=> "[w ]+"

To ucieka. W jaki sposób łańcuch znaków mógłby pozostać niezmieniony i przekształcić go w obiekt wyrażenia regularnego?

cmthakur
źródło

Odpowiedzi:

149

Wygląda na to, że początkowy ciąg znaków musi być w apostrofach (sprawdź tę stronę )

>> str = '[\w\s]+'
 => "[\\w\\s]+" 
>> Regexp.new str
 => /[\w\s]+/ 
alony
źródło
137

Żeby było jasne

  /#{Regexp.quote(your_string_variable)}/

też działa

edit: opakowano your_string_variable w Regexp.quote, dla poprawności.

Sergey Gerasimov
źródło
3
Właśnie dowiedziałem się, że nie możesz w ten sposób dodawać opcji, na przykład /#{your_regex}/#{options}.
pduersteler
Przypuszczam, że mówisz o Railsach? optionsto hash, a Ruby nie jest baaaaardzo dynamiczna =)
Sergey Gerasimov
2
To nie robi tego, o co prosi OP w Rubim 2.1, konwertuje „[\ w \ s] +" => / [w] + /
Luca Spiller,
1
Proszę zauważyć, że odpowiedź została udzielona w 2012 roku :) Wtedy wszystko było idealne
Sergey Gerasimov
4
To był doskonały rok.
Naftuli Kay
35

Ta metoda bezpiecznie usunie wszystkie znaki o specjalnym znaczeniu:

/#{Regexp.quote(your_string)}/

Na przykład .zostanie zmieniony znak ucieczki, ponieważ w przeciwnym razie jest interpretowany jako „dowolny znak”.

Pamiętaj, aby użyć pojedynczego cudzysłowu, chyba że chcesz włączyć zwykłą interpolację ciągów, gdzie ukośnik odwrotny ma specjalne znaczenie.

sandstrom
źródło
2
Fajnie, ponieważ wyjaśnia, w jaki sposób możemy chronić zmienną łańcuchową, która może zawierać znaki (takie jak +.), które byłyby zinterpretowane w wyrażeniu regularnym.
rchampourlier
1
To nie robi tego, o co prosi OP w Rubim 2.1, konwertuje "[\ w \ s] +" => / [w \] \ + /
Luca Spiller
@LucaSpiller musisz użyć łańcucha z pojedynczym cudzysłowem, ukośnik odwrotny jest traktowany jako znak specjalny w łańcuchach umieszczonych w podwójnych cudzysłowach, dlatego np. "\n"Jest znakiem nowej linii, ale nim '\n'nie jest.
sandstrom
8

Używanie notacji%:

%r{\w+}m => /\w+/m

lub

regex_string = '\W+'
%r[#{regex_string}]

Z pomocy :

% r [] Interpolowane wyrażenie regularne (flagi mogą pojawić się po ograniczniku zamykającym)

BitOfUniverse
źródło
To nie robi tego, o co prosi OP w Rubim 2.1, konwertuje "[\ w \ s] +" => / [ws] + /
Luca Spiller
1
@Luca Spiller, dzięki, powinny tam być używane pojedyncze cudzysłowy, zaktualizuję odpowiedź.
BitOfUniverse
5

Klejnot to_regexp może wykonać pracę.

"/[\w\s]+/".to_regexp => /[\w\s]+/

Możesz także użyć modyfikatora:

'/foo/i'.to_regexp => /foo/i

Wreszcie, możesz być bardziej leniwy, używając komendy: Detect

'foo'.to_regexp(detect: true)     #=> /foo/
'foo\b'.to_regexp(detect: true)   #=> %r{foo\\b}
'/foo\b/'.to_regexp(detect: true) #=> %r{foo\b}
'foo\b/'.to_regexp(detect: true)  #=> %r{foo\\b/}
ryan
źródło