簡體   English   中英

如何在正則表達式中使用變量?

[英]How do you use a variable in a regular expression?

我想在 JavaScript 中創建一個String.replaceAll()方法,我認為使用正則表達式是最簡潔的方法。 但是,我不知道如何將變量傳遞給正則表達式。 我已經可以這樣做了,它將用"A"替換"B"的所有實例。

"ABABAB".replace(/B/g, "A");

但我想做這樣的事情:

String.prototype.replaceAll = function(replaceThis, withThis) {
    this.replace(/replaceThis/g, withThis);
};

但顯然這只會替換文本"replaceThis" ......那么我如何將此變量傳遞給我的正則表達式字符串?

您可以構造一個新的RegExp對象,而不是使用/regex\\d/g語法:

var replace = "regex\\d";
var re = new RegExp(replace,"g");

您可以通過這種方式動態創建正則表達式對象。 然后你會做:

"mystring1".replace(re, "newstring");

正如 Eric Wendelin 提到的,您可以執行以下操作:

str1 = "pattern"
var re = new RegExp(str1, "g");
"pattern matching .".replace(re, "regex");

這會產生"regex matching ." . 但是,如果 str1 是"." ,它將失敗。 . 您希望結果是"pattern matching regex" ,用"regex"替換句點,但結果是......

regexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregexregex

這是因為,雖然"." 是一個字符串,在 RegExp 構造函數中它仍然被解釋為一個正則表達式,表示任何非換行符,表示字符串中的每個字符。 為此,以下功能可能有用:

 RegExp.quote = function(str) {
     return str.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
 };

然后你可以這樣做:

str1 = "."
var re = new RegExp(RegExp.quote(str1), "g");
"pattern matching .".replace(re, "regex");

產生"pattern matching regex"

"ABABAB".replace(/B/g, "A");

與往常一樣:除非必須,否則不要使用正則表達式。 對於簡單的字符串替換,成語是:

'ABABAB'.split('B').join('A')

那么您不必擔心 Gracenotes 的回答中提到的引用問題。

如果你想獲得所有的出現( g ),不區分大小寫( i ),並使用邊界,以便它不是另一個單詞中的單詞( \\\\b ):

re = new RegExp(`\\b${replaceThis}\\b`, 'gi');

例子:

let inputString = "I'm John, or johnny, but I prefer john.";
let replaceThis = "John";
let re = new RegExp(`\\b${replaceThis}\\b`, 'gi');
console.log(inputString.replace(re, "Jack")); // I'm Jack, or johnny, but I prefer Jack.

對於希望通過match方法使用變量的任何人,這對我有用:

var alpha = 'fig';
'food fight'.match(alpha + 'ht')[0]; // fight

這:

var txt=new RegExp(pattern,attributes);

相當於:

var txt=/pattern/attributes;

請參閱http://www.w3schools.com/jsref/jsref_obj_regexp.asp

this.replace( new RegExp( replaceThis, 'g' ), withThis );

您需要動態構建正則表達式,為此您必須使用帶有 escaping 的new RegExp(string)構造函數

jQuery UI 自動完成小部件中有一個名為$.ui.autocomplete.escapeRegex的內置函數:

它將采用單個字符串參數並轉義所有正則表達式字符,使結果可以安全地傳遞給new RegExp()

如果您不使用 jQuery UI,您可以從源代碼復制其定義:

function escapeRegex( value ) {
    return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
}

並像這樣使用它:

"[z-a][z-a][z-a]".replace(new RegExp(escapeRegex("[z-a]"), "g"), "[a-z]");
//            escapeRegex("[z-a]")       -> "\[z\-a\]"
// new RegExp(escapeRegex("[z-a]"), "g") -> /\[z\-a\]/g
// end result                            -> "[a-z][a-z][a-z]"
String.prototype.replaceAll = function (replaceThis, withThis) {
   var re = new RegExp(replaceThis,"g"); 
   return this.replace(re, withThis);
};
var aa = "abab54..aba".replaceAll("\\.", "v");

用這個工具測試

String.prototype.replaceAll = function(a, b) {
    return this.replace(new RegExp(a.replace(/([.?*+^$[\]\\(){}|-])/ig, "\\$1"), 'ig'), b)
}

像這樣測試它:

var whatever = 'Some [b]random[/b] text in a [b]sentence.[/b]'

console.log(whatever.replaceAll("[", "<").replaceAll("]", ">"))

還有Steven Penny 回答的 CoffeeScript 版本,因為這是 Google 結果的第 2 位……即使 CoffeeScript 只是刪除了很多字符的 JavaScript……;)

baz = "foo"
filter = new RegExp(baz + "d")
"food fight".match(filter)[0] // food

在我的特殊情況下:

robot.name = hubot
filter = new RegExp(robot.name)
if msg.match.input.match(filter)
  console.log "True!"

為了滿足我將變量/別名/函數插入正則表達式的需要,這就是我想出的:

oldre = /xx\(""\)/;
function newre(e){
    return RegExp(e.toString().replace(/\//g,"").replace(/xx/g, yy), "g")
};

String.prototype.replaceAll = this.replace(newre(oldre), "withThis");

其中“oldre”是我要插入變量的原始正則表達式,“xx”是該變量/別名/函數的占位符,“yy”是實際的變量名稱、別名或函數。

您可以將字符串用作正則表達式。 不要忘記使用新的 RegExp

例子:

var yourFunction = new RegExp(
        '^-?\\d+(?:\\.\\d{0,' + yourVar + '})?'
      )

這是另一個 replaceAll 實現:

    String.prototype.replaceAll = function (stringToFind, stringToReplace) {
        if ( stringToFind == stringToReplace) return this;
        var temp = this;
        var index = temp.indexOf(stringToFind);
        while (index != -1) {
            temp = temp.replace(stringToFind, stringToReplace);
            index = temp.indexOf(stringToFind);
        }
        return temp;
    };

如果$1不適合您,您可以使用它:

var pattern = new RegExp("amman", "i");
"abc Amman efg".replace(pattern, "<b>" + "abc Amman efg".match(pattern)[0] + "</b>");

您的解決方案在這里:

將變量傳遞給正則表達式

我已經實現的一個是通過從文本字段中獲取值,這是您要替換的文本字段,另一個是“替換為”文本字段,從變量中的文本字段獲取值並將變量設置為 RegExp功能進一步替換。 就我而言,我使用的是 jQuery,但您也可以僅通過 JavaScript 來完成。

JavaScript 代碼:

  var replace =document.getElementById("replace}"); // getting a value from a text field with I want to replace
  var replace_with = document.getElementById("with"); //Getting the value from another text fields with which I want to replace another string.

  var sRegExInput = new RegExp(replace, "g");
  $("body").children().each(function() {
    $(this).html($(this).html().replace(sRegExInput,replace_with));
  });

這段代碼在按鈕的 Onclick 事件上,你可以把它放在一個函數中調用。

所以現在你可以在替換函數中傳遞一個變量。

雖然您可以動態創建正則表達式(根據對這個問題的其他回復),但我會從類似的帖子中回應我的評論: String.replace()的函數形式非常有用,在許多情況下減少了對動態創建的 RegExp 對象。 (這有點痛苦,因為您必須將 RegExp 構造函數的輸入表示為字符串,而不是使用斜杠 /[AZ]+/ regexp 文字格式)

這些答案對我來說都不清楚。 我最終在如何在 JavaScript 的替換函數中使用變量找到了一個很好的解釋

簡單的答案是:

var search_term = new RegExp(search_term, "g");
text = text.replace(search_term, replace_term);

例如:

 $("button").click(function() { Find_and_replace("Lorem", "Chocolate"); Find_and_replace("ipsum", "ice-cream"); }); function Find_and_replace(search_term, replace_term) { text = $("textbox").html(); var search_term = new RegExp(search_term, "g"); text = text.replace(search_term, replace_term); $("textbox").html(text); }
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <textbox> Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum </textbox> <button>Click me</button>

這個自調用函數將使用索引迭代 replacerItems,並在每次傳遞時全局更改字符串上的 replacerItems[index]。

  const replacerItems = ["a", "b", "c"];    

    function replacer(str, index){
          const item = replacerItems[index];
          const regex = new RegExp(`[${item}]`, "g");
          const newStr = str.replace(regex, "z");
          if (index < replacerItems.length - 1) {
            return replacer(newStr, index + 1);
          }
          return newStr;
    }

// console.log(replacer('abcdefg', 0)) will output 'zzzdefg'

您總是可以重復使用indexOf

String.prototype.replaceAll = function(substring, replacement) {
    var result = '';
    var lastIndex = 0;

    while(true) {
        var index = this.indexOf(substring, lastIndex);
        if(index === -1) break;
        result += this.substring(lastIndex, index) + replacement;
        lastIndex = index + substring.length;
    }

    return result + this.substring(lastIndex);
};

當替換包含匹配項時,這不會進入無限循環。

對於沒有正則表達式的多個替換,我使用以下內容:

      let str = "I am a cat man. I like cats";
      let find = "cat";
      let replace = "dog";


      // Count how many occurrences there are of the string to find 
      // inside the str to be examined.
      let findCount = str.split(find).length - 1;

      let loopCount = 0;

      while (loopCount < findCount) 
      {
        str = str.replace(find, replace);
        loopCount = loopCount + 1;
      }  

      console.log(str);
      // I am a dog man. I like dogs

解決方案的重要部分在這里找到

作為一個相對的 JavaScript 新手,已注意到/贊賞已接受的答案https://stackoverflow.com/a/494046/1904943 ,但它不是很直觀。

這是一個更簡單的解釋,例如(使用簡單的 JavaScript IDE )。

myString = 'apple pie, banana loaf';

console.log(myString.replaceAll(/pie/gi, 'PIE'))
// apple PIE, banana loaf

console.log(myString.replaceAll(/\bpie\b/gi, 'PIE'))
// apple PIE, banana loaf

console.log(myString.replaceAll(/pi/gi, 'PIE'))
// apple PIEe, banana loaf

console.log(myString.replaceAll(/\bpi\b/gi, 'PIE'))
// [NO EFFECT] apple pie, banana loaf

const match_word = 'pie';

console.log(myString.replaceAll(/match_word/gi, '**PIE**'))
// [NO EFFECT] apple pie, banana loaf

console.log(myString.replaceAll(/\b`${bmatch_word}`\b/gi, '**PIE**'))
// [NO EFFECT] apple pie, banana loaf

// ----------------------------------------
// ... new RegExp(): be sure to \-escape your backslashes: \b >> \\b ...

const match_term = 'pie';
const match_re = new RegExp(`(\\b${match_term}\\b)`, 'gi')

console.log(myString.replaceAll(match_re, 'PiE'))
// apple PiE, banana loaf

console.log(myString.replace(match_re, '**PIE**'))
// apple **PIE**, banana loaf

console.log(myString.replaceAll(match_re, '**PIE**'))
// apple **PIE**, banana loaf

應用

例如:替換(顏色突出顯示)字符串/句子中的單詞,[可選地]如果搜索詞匹配超過用戶定義的匹配詞的比例。

注意:匹配詞的原始字符大小寫被保留。 hl :突出顯示; re :正則表達式 | 正則表達式

mySentence = "Apple, boOk? BOoks; booKEd. BookMark, 'BookmarkeD', bOOkmarks! bookmakinG, Banana; bE, BeEn, beFore."

function replacer(mySentence, hl_term, hl_re) {
    console.log('mySentence [raw]:', mySentence)
    console.log('hl_term:', hl_term, '| hl_term.length:', hl_term.length)
    cutoff = hl_term.length;
    console.log('cutoff:', cutoff)

    // `.match()` conveniently collects multiple matched items
    // (including partial matches) into an [array]
    const hl_terms  = mySentence.toLowerCase().match(hl_re, hl_term);
    if (hl_terms == null) {
        console.log('No matches to hl_term "' + hl_term + '"; echoing input string then exiting ...')
        return mySentence;
    }
    console.log('hl_terms:', hl_terms)
    for (let i = 0;  i < hl_terms.length; i++) {
        console.log('----------------------------------------')
        console.log('[' + i + ']:', hl_terms[i], '| length:', hl_terms[i].length, '| parseInt(0.7(length)):', parseInt(0.7*hl_terms[i].length))
        // TEST: if (hl_terms[i].length >= cutoff*10) {
        if (cutoff >= parseInt(0.7 * hl_terms[i].length)) {
            var match_term = hl_terms[i].toString();

            console.log('matched term:', match_term, '[cutoff length:', cutoff, '| 0.7(matched term length):', parseInt(0.7 * hl_terms[i].length))

            const match_re = new RegExp(`(\\b${match_term}\\b)`, 'gi')

            mySentence = mySentence.replaceAll(match_re, '<font style="background:#ffe74e">$1</font>');
        }
        else {
            var match_term = hl_terms[i].toString();
            console.log('NO match:', match_term, '[cutoff length:', cutoff, '| 0.7(matched term length):', parseInt(0.7 * hl_terms[i].length))
        }
    }
    return mySentence;
}

// TESTS:
// const hl_term = 'be';
// const hl_term = 'bee';
// const hl_term = 'before';
// const hl_term = 'book';
const hl_term = 'bookma';
// const hl_term = 'Leibniz';

// This regex matches from start of word:
const hl_re = new RegExp(`(\\b${hl_term}[A-z]*)\\b`, 'gi')

mySentence = replacer(mySentence, hl_term, hl_re);
console.log('mySentence [processed]:', mySentence)

輸出

mySentence [raw]: Apple, boOk? BOoks; booKEd. BookMark, 'BookmarkeD',
bOOkmarks! bookmakinG, Banana; bE, BeEn, beFore.

hl_term: bookma | hl_term.length: 6
cutoff: 6
hl_terms: Array(4) [ "bookmark", "bookmarked", "bookmarks", "bookmaking" ]

----------------------------------------
[0]: bookmark | length: 8 | parseInt(0.7(length)): 5
matched term: bookmark [cutoff length: 6 | 0.7(matched term length): 5
----------------------------------------
[1]: bookmarked | length: 10 | parseInt(0.7(length)): 7
NO match: bookmarked [cutoff length: 6 | 0.7(matched term length): 7
----------------------------------------
[2]: bookmarks | length: 9 | parseInt(0.7(length)): 6
matched term: bookmarks [cutoff length: 6 | 0.7(matched term length): 6
----------------------------------------
[3]: bookmaking | length: 10 | parseInt(0.7(length)): 7
NO match: bookmaking [cutoff length: 6 | 0.7(matched term length): 7

mySentence [processed]: Apple, boOk? BOoks; booKEd.
<font style="background:#ffe74e">BookMark</font>, 'BookmarkeD',
<font style="background:#ffe74e">bOOkmarks</font>! bookmakinG,
Banana; bE, BeEn, beFore.

如果您使用正確的語法傳遞變量,則可以使用下面的代碼執行此操作。

這具有在同一變量中使用標志的額外好處。

此外,當涉及\\w等時,您不必在正則表達式中雙重轉義\\等。

 var str = 'regexVariable example: This is my example of RegExp replacing with a regexVariable.' var reVar = /(.*?)(regex\\w+?iable)(.+?)/gi; var resStr = str.replace(new RegExp(reVar), '$1 :) :) :) $2 :) :) :)$3'); console.log(resStr); // Returns: // :) :) :) regexVariable :) :) :) example: This is my example of RegExp replacing with a :) :) :) regexVariable :) :) :).

根據 OP 示例的原型版本:

 var str = 'regexVariable prototype: This is my example of RegExp replacing with a regexVariable.' String.prototype.regexVariable = function(reFind, reReplace) { return str.replace(new RegExp(reFind), reReplace); } var reVar = /(.*?)(regex\\w+?iable)(.+?)/gi; console.log(str.regexVariable(reVar, '$1 :) :) :) $2 :) :) :)$3')); // Returns: // :) :) :) regexVariable :) :) :) prototype: This is my example of replacing with a :) :) :) regexVariable :) :) :).

示例:正則表達式以

function startWith(char, value) {
    return new RegExp(`^[${char}]`, 'gi').test(value);
}

我在這里和 stackoverflow 或類似論壇上的其他公開票證中找到了很多帶有奇怪示例的答案。

在我看來,這是最簡單的選擇,您可以將變量作為模板文字字符串;

const someString = "abc";
const regex = new RegExp(`^ someregex ${someString} someregex $`);

如您所見,我沒有在開頭或結尾提出斜杠,RegExp 構造函數將重建有效的正則表達式文字。 也適用於 yup 匹配 function。

當有一個更簡單的答案仍然可以使用正則表達式完成工作時,所有這些答案似乎都非常復雜。

String.prototype.replaceAll = function(replaceThis, withThis) {
    const expr = `${replaceThis}`
    this.replace(new RegExp(expr, "g"), withThis);
};

解釋

RegExp構造函數采用 2 arguments:表達式和標志。 通過在表達式中使用模板字符串,我們可以將變量傳遞給 class,它會將其轉換為/(value of the replaceThis variable)/g

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM