คุณจะใช้ตัวแปรในการแสดงออกปกติได้อย่างไร


1378

ฉันต้องการสร้างString.replaceAll()วิธีการใน JavaScript และฉันคิดว่าการใช้ regex จะเป็นวิธีที่สั้นที่สุดที่จะทำ อย่างไรก็ตามฉันไม่สามารถหาวิธีส่งตัวแปรไปยัง regex ได้ ฉันจะทำอย่างนี้แล้วซึ่งจะแทนที่ทุกกรณีของกับ"B""A"

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

แต่ฉันต้องการทำสิ่งนี้:

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

แต่แน่นอนว่าสิ่งนี้จะแทนที่ข้อความเท่านั้น"replaceThis"... ดังนั้นฉันจะส่งตัวแปรนี้ไปยังสตริง regex ของฉันได้อย่างไร


9
โปรดทราบว่าขณะนี้เรากำลังดำเนินการเกี่ยวกับการเพิ่มฟังก์ชันนี้ใน JavaScriptหากคุณมีความคิดเห็นเกี่ยวกับเรื่องนี้โปรดเข้าร่วมการสนทนา
Benjamin Gruenbaum

คำตอบ:


1840

แทนที่จะใช้/regex/gไวยากรณ์คุณสามารถสร้างวัตถุRegExpใหม่:

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

คุณสามารถสร้างวัตถุ Regex แบบไดนามิกได้ด้วยวิธีนี้ จากนั้นคุณจะทำ:

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

272
หากคุณต้องการใช้นิพจน์เช่น/\/word\:\w*$/นั้นให้แน่ใจว่าได้หลีกเลี่ยงแบ็กสแลชของคุณ: new RegExp( '\\/word\\:\\w*$' ).
Jonathan Swinney

2
@gravityboy คุณสามารถทำ ('' + myNumber) .replace (/ 10 / g, 'a') หรือถ้าคุณต้องการเลขฐานสิบหกคุณสามารถทำ parseInt ('' + myNumber, 16) เพื่อแปลงเป็นเลขฐานสิบหกจากทศนิยม
Eric Wendelin

29
คำถามแสดงให้เห็นว่า RegEx ใช้เพื่อทำการแทนที่สตริงคงที่เท่านั้น ดังนั้นนี่คือคำตอบที่ผิดเพราะจะล้มเหลวหากสตริงมีอักขระเมตา RegEx น่า
เสียดายที่

16
ตัวอย่างของการผ่านตัวแปรนี้จะทำให้คำตอบที่ดี ฉันยังคงดิ้นรนหลังจากอ่านข้อความนี้
Goose

3
@JonathanSwinney: /ไม่มีความหมายพิเศษถ้าคุณสร้าง regex จาก string ดังนั้นคุณไม่จำเป็นต้องหลบหนี /\/word\:\w*$/ควรเป็นnew RegExp('/word\\:\\w*$')
DávidHorváth

211

ดังที่ 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"ยอมให้


4
คุณรู้ไหมว่าพารามิเตอร์แรกที่จะแทนที่สามารถเป็นสตริงปกติและไม่จำเป็นต้องเป็น regexp? str1 = "."; การแจ้งเตือน ("การจับคู่รูปแบบ". แทนที่ (str1, "string"));
บาง

@ บางคน: แน่นอน นั่นเป็นเพราะตัวอย่างข้างต้นไม่สำคัญ เมื่อคุณต้องการค้นหาหรือแทนที่รูปแบบที่รวมกับสตริงปกติให้ทำ str.match (RegExp ใหม่ ("https?: //" + RegExp.escape (myDomainName)) เป็นเรื่องน่ารำคาญที่ฟังก์ชัน escape เป็น ไม่ได้สร้างขึ้นมา
Gracenotes

(ต่อ) บวก, ชัดเจนว่า JC Grubbs ต้องการทดแทนระดับโลก; การใช้การแทนที่แบบโกลบอลด้วย String.replace (String, String) อาจช้าสำหรับอินพุตขนาดใหญ่ ฉันแค่พูดว่าโซลูชันสองอันดับแรกมีข้อผิดพลาดและจะล้มเหลวอย่างไม่คาดคิดในอินพุตที่แน่นอน
Gracenotes

4
developer.mozilla.org/en-US/docs/JavaScript/Guide/...ข้อเสนอฟังก์ชั่นที่คล้ายกัน แต่พวกเขาไม่รวมและรวมถึง- =!:/
chbrown

8
คำที่ถูกต้องคือ "escape" ไม่ใช่ "quote" แค่ BTW
Lawrence Dol

118

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

เช่นเคย: อย่าใช้ regex เว้นแต่คุณจะต้อง สำหรับการแทนที่สตริงอย่างง่ายสำนวนนั้นคือ:

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

จากนั้นคุณไม่ต้องกังวลเกี่ยวกับปัญหาที่กล่าวถึงในคำตอบของ Gracenotes


11
และคุณวัดว่านี่เร็วกว่า regex หรือไม่
Mitar

3
ดูเหมือนว่าจะดีกว่านี้โดยเฉพาะเมื่อต้องการจับคู่กับอักขระพิเศษ regex เช่น '.'
Krease

1
อืม ... ไม่แบ่ง RegExp ด้วยเช่นกัน ถ้าเป็นเช่นนั้นมันจะไม่ทำให้เกิดปัญหาเดียวกันได้หรือ อย่างไรก็ตาม ... .split (). join () อาจช้ากว่าในบางแพลตฟอร์มเพราะเป็นสองการทำงานในขณะที่. แทนที่ () เป็นการดำเนินการหนึ่งครั้งและอาจได้รับการปรับให้เหมาะสม

5
@ PacMan -: ทั้งสองsplitและreplaceสามารถใช้สตริงหรือRegExpวัตถุ ปัญหาที่ไม่มีreplaceนั่นsplitก็คือเมื่อคุณใช้สตริงคุณจะได้รับการแทนที่เพียงครั้งเดียว
bobince

1
เกณฑ์มาตรฐานที่นี่: jsperf.com/replace-vs-split-join-vs-replaceall/23
Wagner da Silva

38

หากคุณต้องการรับเหตุการณ์ทั้งหมด ( 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.

ขอบคุณ! (AFAICT, คุณเป็นเพียงคำตอบอย่างชัดเจนกับ Emacs / rxแก้ไขสไตล์ผ่านทางสายแม่แบบ.)
sam boosalis

34

สำหรับทุกคนที่ต้องการใช้ตัวแปรพร้อมวิธีจับคู่สิ่งนี้ใช้ได้สำหรับฉัน

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

31

นี้:

var txt=new RegExp(pattern,attributes);

เทียบเท่ากับสิ่งนี้:

var txt=/pattern/attributes;

ดูhttp://www.w3schools.com/jsref/jsref_obj_regexp.asp


20
อ๋อ แต่ในตัวอย่างแรกมันใช้patternเป็นตัวแปรในวันที่ 2 เป็นสายอักขระ
vladkras


14

คุณต้องการสร้างการแสดงออกปกติแบบไดนามิกและสำหรับการแก้ปัญหาที่เหมาะสมคือการใช้ตัวnew RegExp(string)สร้าง เพื่อให้ผู้สร้างในการรักษาตัวละครพิเศษอย่างแท้จริงคุณต้องหลบหนีพวกเขา มีฟังก์ชันในตัวในวิดเจ็ตการเติมข้อความอัตโนมัติ jQuery UI ที่เรียกว่า$.ui.autocomplete.escapeRegex:

[... ] คุณสามารถใช้ประโยชน์จาก$.ui.autocomplete.escapeRegexฟังก์ชั่นใน ตัว มันจะใช้อาร์กิวเมนต์สายเดียวและหลบหนีอักขระ regex 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]"


5
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("]", ">"))

4

นี่คือการใช้งาน 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;
    };

4

และคำตอบของสตีเวนเพนนีรุ่น coffeescript เนื่องจากเป็น # 2 google result .... แม้ว่ากาแฟจะเป็นเพียงจาวาสคริปต์ที่มีตัวละครจำนวนมากถูกลบออก ... ;)

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!"

ทำไมต้องลงคะแนน coffeescript -IS- จาวาสคริปต์ที่มีไวยากรณ์เฉพาะของตัวเอง
คม

robot.name=hubotไม่ใช่จาวาสคริปต์
codepleb

3

ในขณะที่คุณสามารถสร้าง RegExp แบบไดนามิก (ตามคำตอบอื่น ๆ ของคำถามนี้) ฉันจะสะท้อนความคิดเห็นของฉันจากโพสต์ที่คล้ายกัน : รูปแบบการทำงานของString.replace ()มีประโยชน์อย่างมากและในหลาย ๆ กรณีลดความต้องการ วัตถุ RegExp ที่สร้างขึ้นแบบไดนามิก (ซึ่งเป็นชนิดของความเจ็บปวด 'สาเหตุที่คุณต้องแสดงความคิดเห็นไปยังตัวสร้าง RegExp เป็นสตริงแทนที่จะใช้เครื่องหมายทับ / [AZ] + / รูปแบบตัวอักษร regexp)


3

เพื่อตอบสนองความต้องการของฉันในการแทรกตัวแปร / alias / function ลงใน Regular Expression นี่คือสิ่งที่ฉันได้รับ:

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' เป็น regexp ดั้งเดิมที่ฉันต้องการแทรกตัวแปร 'xx' เป็นตัวยึดสำหรับตัวแปร / alias / function นั้นและ 'yy' เป็นชื่อตัวแปรจริงนามแฝงหรือฟังก์ชัน


2

คุณสามารถใช้สิ่งนี้หาก $ 1 ไม่ได้ทำงานกับคุณ

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

1

คุณสามารถใช้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);
};

สิ่งนี้จะไม่เข้าสู่วงวนไม่สิ้นสุดเมื่อการแทนที่มีการแข่งขัน


1

ทางออกของคุณอยู่ที่นี่:

ส่งผ่านตัวแปรไปยังนิพจน์ทั่วไป

สิ่งที่ฉันได้ดำเนินการคือการรับค่าจากฟิลด์ข้อความซึ่งเป็นสิ่งที่คุณต้องการแทนที่และอีกอันคือ "แทนที่ด้วย" ฟิลด์ข้อความรับค่าจากฟิลด์ข้อความในตัวแปรและตั้งค่าตัวแปรเป็น 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 ของปุ่มคุณสามารถใส่สิ่งนี้ในฟังก์ชั่นการโทร

ดังนั้นตอนนี้คุณสามารถส่งผ่านตัวแปรในฟังก์ชั่นแทนที่


ตัวแปร replace_with ของคุณจะมีองค์ประกอบ DOM ไม่ใช่ค่าตัวเอง
Ben Taliadoros

1

ฟังก์ชันการเรียกตนเองนี้จะวนซ้ำกว่า 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'

0

ไม่มีคำตอบใดที่ชัดเจนสำหรับฉัน ในที่สุดฉันก็พบคำอธิบายที่ดีที่http://burnignorance.com/php-programming-tips/how-to-use-a-variable-in-replace-function-of-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>


1
คุณเขียนทับตัวแปรการปิดไม่จำเป็นต้องใช้varที่นี่ นอกจากนี้ถ้าคุณผ่าน\bหรือ\1มันจะทำลาย
CyberAP

0

สำหรับการแทนที่หลายรายการโดยไม่มีการแสดงออกปกติฉันไปกับต่อไปนี้:

      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

ส่วนสำคัญของการแก้ปัญหาอยู่ที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.