JavaScript Regex: Jak wstawić zmienną do wyrażenia regularnego?

206

Na przykład:

function(input){
    var testVar = input;
    string = ...
    string.replace(/ReGeX + testVar + ReGeX/, "replacement")
}

Ale to oczywiście nie działa :) Czy jest na to sposób?

Adam
źródło
11
Pamiętaj, że jeśli pozwolisz użytkownikowi podać tę zmienną, złośliwemu użytkownikowi łatwo jest zawiesić aplikację poprzez katastrofalne cofnięcie.
Tim Pietzcker
2
co to jest „ReGeX”? czy to jest nazwa zmiennej? sprawia, że ​​odpowiedzi są mylące, sugerując, że jest to część konstrukcji RegExp (na wypadek, gdyby czytelnik nie widział tych dziwnych znaków w pytaniu).
Eduard,

Odpowiedzi:

272
const regex = new RegExp(`ReGeX${testVar}ReGeX`);
...
string.replace(regex, "replacement");

Aktualizacja

W przypadku niektórych komentarzy należy zauważyć, że możesz chcieć uciec od zmiennej, jeśli istnieje możliwość wystąpienia złośliwej zawartości (np. Zmienna pochodzi z danych wprowadzonych przez użytkownika)

Aktualizacja ES6

W 2019 r. Byłoby to zwykle napisane przy użyciu ciągu szablonu, a powyższy kod został zaktualizowany. Oryginalna odpowiedź brzmiała:

var regex = new RegExp("ReGeX" + testVar + "ReGeX");
...
string.replace(regex, "replacement");
Jason McCreary
źródło
5
Upewnij się, aby uciec od łańcucha! Zobacz odpowiedź @zzzzBov
jtpereyda
To nie działa w moim przypadku, czy mógłbyś rzucić okiem na ten jsfiddle i dać mi znać, co muszę zrobić, jeśli chcę ustawić dynamikę kodu kraju w regexwyrażeniu
Kirankumar Dafda
10
Jedną ważną rzeczą do zapamiętania jest to, że w regularnych ciągach znak \ musi być poprzedzony znakiem ucieczki, podczas gdy w dosłownym wyrażeniu regularnym (zwykle) znak / musi być poprzedzony znakiem ucieczki. Tak się /\w+\//istajenew RegExp("\\w+/", "i")
Ali
3
Co powiesz na / g?
Qian Chen,
Chłopaki, muszę podzielić to wyrażenie regularne /[^0-9.-]/g na dwie części: / [^ 0-9 i -] / g Jak to zrobić?
maks.
79

Możesz użyć obiektu RegExp:

var regexstring = "whatever";
var regexp = new RegExp(regexstring, "gi");
var str = "whateverTest";
var str2 = str.replace(regexp, "other");
document.write(str2);

Następnie możesz budować regexstringw dowolny sposób.

Możesz przeczytać więcej na ten temat tutaj .

steinar
źródło
var characterCount = parseInt (attrs.limitCharacterCount); console.log (characterCount); var specialCharactersValidation = new RegExp ("/ ^ [a-zA-Z0-9] {" + characterCount + "} $ /"); / \ / ^ [a-zA-Z0-9] {7} $ \ // requestShipmentDirectives.js: 76 false main.js: 46 Uncaught TypeError: Nie można odczytać właściwości „offsetWidth” o wartości null To właśnie dzieje się, gdy robię RegEx Dynamic.
Ankit Tanna
31

Aby zbudować wyrażenie regularne ze zmiennej w JavaScript, musisz użyć RegExpkonstruktora z parametrem string.

function reg(input) {
    var flags;
    //could be any combination of 'g', 'i', and 'm'
    flags = 'g';
    return new RegExp('ReGeX' + input + 'ReGeX', flags);
}

oczywiście jest to bardzo naiwny przykład. Zakłada się, że inputpoprawnie zapisano go dla wyrażenia regularnego. Jeśli masz do czynienia z wprowadzaniem danych przez użytkownika lub po prostu chcesz wygodniej dopasowywać znaki specjalne, musisz uciec od znaków specjalnych :

function regexEscape(str) {
    return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
}

function reg(input) {
    var flags;
    //could be any combination of 'g', 'i', and 'm'
    flags = 'g';
    input = regexEscape(input);
    return new RegExp('ReGeX' + input + 'ReGeX', flags);
}
zzzzBov
źródło
Jedynym sposobem, w jaki mi to działało, było usunięcie ReGeXtekstu. Użyłem więc:return new RegExp(input, flags);
Michael Rader,
2
@MichaelRader, tak, tekst „ReGeX” był częścią pytania i został użyty jako przykład, a nie jako coś, co jest wymagane, aby kod działał.
zzzzBov
1
Lol właśnie zdał sobie sprawę, że to tylko twój symbol zastępczy, ale jako noob zajęło mi to trochę czasu, żeby to rozgryźć. Dzięki.
Michael Rader
Rozumiem, dlaczego ciąg musi być usuwany. Ale dlaczego „\\ $ &” jest używane jako zamiennik
Sherin Binu
2
\\reprezentuje pojedynczy \znak, $&jest dopasowanym podciągiem .
zzzzBov
7

jeśli używasz literałów szablonu es6 są opcją ...

string.replace(new RegExp(`ReGeX${testVar}ReGeX`), "replacement")
shunryu111
źródło
nie działa z literałami szablonów. Używam wyrażenia regularnego do sprawdzania poprawności hasła w mojej aplikacji i chciałem sparametryzować maksymalną i minimalną długość w moim ciągu wyrażeń regularnych i to nie działa. `` `const newRegExp = new RegExp ( ^[^\s]{${4},${32}}$); export const validatePassword = wartość => wartość.match (newRegExp); ``
p7adams
6

Zawsze możesz podać wyrażenie regularne jako ciąg znaków, tj "ReGeX" + testVar + "ReGeX". Być może będziesz musiał uciec przed niektórymi znakami w ciągu (np. Podwójny cudzysłów), ale w większości przypadków jest to równoważne.

Możesz także użyć RegExpkonstruktora, aby przekazać flagi ( zobacz dokumentację ).

Nikita Rybak
źródło
3

Możesz utworzyć wyrażenia regularne w JS na jeden z dwóch sposobów:

  1. Używanie literału wyrażenia regularnego - /ab{2}/g
  2. Korzystanie z konstruktora wyrażeń regularnych - new RegExp("ab{2}", "g").

Literały wyrażeń regularnych są stałe i nie można ich używać ze zmiennymi. Można to osiągnąć za pomocą konstruktora. Struktura konstruktora RegEx jest

new RegExp(regularExpressionString, modifiersString)

Zmienne można osadzać jako część regularExpressionString. Na przykład,

var pattern="cd"
var repeats=3
new RegExp(`${pattern}{${repeats}}`, "g") 

Będzie pasować do każdego wyglądu wzoru cdcdcd.

Ben Carp
źródło
2

Oto całkiem bezużyteczna funkcja, która zwraca wartości zawinięte przez określone znaki. :)

jsfiddle: https://jsfiddle.net/squadjot/43agwo6x/

function getValsWrappedIn(str,c1,c2){
    var rg = new RegExp("(?<=\\"+c1+")(.*?)(?=\\"+c2+")","g"); 
    return str.match(rg);
    }

var exampleStr = "Something (5) or some time (19) or maybe a (thingy)";
var results =  getValsWrappedIn(exampleStr,"(",")")

// Will return array ["5","19","thingy"]
console.log(results)
Jakob Sternberg
źródło
2

zaakceptowana odpowiedź nie działa dla mnie i nie jest zgodna z przykładami MDN

patrz sekcja „Opis” w powyższym linku

Wybrałbym następujące, które działają dla mnie:

let stringThatIsGoingToChange = 'findMe';
let flagsYouWant = 'gi' //simple string with flags
let dynamicRegExp = new RegExp(`${stringThatIsGoingToChange}`, flagsYouWant)

// that makes dynamicRegExp = /findMe/gi
Timothy Mitchell
źródło
1
Wciąż działa. Problem polega na tym, że „ReGeX” + testVar + „ReGeX” sprawia, że ​​rozwiązanie jest mylące. Dodanie faktycznego przykładu wyjaśniłoby, moim zdaniem, pewne rzeczy. var testVar = „321”; var regex = new RegExp („[” + testVar + ”] {2}”, „g”); // powyżej odpowiednika / [321] {2} / g
HelloWorldPeace
1

Trzeba tylko najpierw przygotować zmienną łańcuchową, a następnie przekonwertować ją na RegEx.

na przykład:

Chcesz dodać minLengthi MaxLengthza pomocą zmiennej do RegEx:

function getRegEx() {
    const minLength = "5"; // for exapmle: min is 5
    const maxLength = "12"; // for exapmle: man is 12

    var regEx = "^.{" + minLength + ","+ maxLength +"}$"; // first we make a String variable of our RegEx
    regEx = new RegExp(regEx, "g"); // now we convert it to RegEx

    return regEx; // In the end, we return the RegEx
}

teraz, jeśli zmienisz wartość MaxLengthlub MinLength, to zmieni się we wszystkich RegExs.

Mam nadzieję, że się przydadzę. Przepraszam również za mój angielski.

Abbas Habibnejad
źródło