คุณเข้าถึงกลุ่มที่ตรงกันในนิพจน์ปกติของ JavaScript ได้อย่างไร


1368

ฉันต้องการจับคู่ส่วนของสตริงโดยใช้นิพจน์ทั่วไปจากนั้นเข้าถึงสตริงย่อยที่วงเล็บ:

var myString = "something format_abc"; // I want "abc"

var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);

console.log(arr);     // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]);  // Prints: undefined  (???)
console.log(arr[0]);  // Prints: format_undefined (!!!)

ผมทำอะไรผิดหรือเปล่า?


ฉันพบว่าไม่มีอะไรผิดปกติกับรหัสนิพจน์ทั่วไปด้านบน: สตริงจริงที่ฉันทดสอบเทียบคือ:

"date format_%A"

การรายงานว่า "% A" ไม่ได้กำหนดดูเหมือนว่าจะเป็นพฤติกรรมที่แปลกมาก แต่ไม่เกี่ยวข้องโดยตรงกับคำถามนี้ดังนั้นฉันจึงเปิดขึ้นมาใหม่ทำไมสตริงย่อยที่ตรงกันจึงกลับมา "ไม่ได้กำหนด" ใน JavaScript .


ปัญหาคือconsole.logใช้พารามิเตอร์ของมันเช่นprintfคำสั่งและเนื่องจากสตริงที่ฉันบันทึก ( "%A") มีค่าพิเศษมันจึงพยายามหาค่าของพารามิเตอร์ถัดไป

คำตอบ:


1673

คุณสามารถเข้าถึงกลุ่มจับภาพเช่นนี้:

var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var match = myRegexp.exec(myString);
console.log(match[1]); // abc

และหากมีการแข่งขันหลายรายการคุณสามารถทำซ้ำได้มากกว่า:

var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
match = myRegexp.exec(myString);
while (match != null) {
  // matched text: match[0]
  // match start: match.index
  // capturing group n: match[n]
  console.log(match[0])
  match = myRegexp.exec(myString);
}

แก้ไข: 2019-09-10

อย่างที่คุณเห็นวิธีการย้ำผ่านการแข่งขันหลาย ๆ ครั้งนั้นไม่ใช่เรื่องง่าย นำไปสู่ข้อเสนอของString.prototype.matchAllวิธีการนี้ วิธีการใหม่นี้คาดว่าจะจัดส่งในข้อกำหนด ECMAScript 2020 มันทำให้เราสะอาด API และแก้ปัญหาหลายอย่าง มันเริ่มต้นลงจอดบนเบราว์เซอร์หลักและเครื่องมือ JS เป็นChrome 73+ / Node 12+และ Firefox 67+

เมธอดส่งคืนตัววนซ้ำและใช้ดังต่อไปนี้:

const string = "something format_abc";
const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
const matches = string.matchAll(regexp);
    
for (const match of matches) {
  console.log(match);
  console.log(match.index)
}

เมื่อส่งคืนตัววนซ้ำเราสามารถบอกว่าขี้เกียจนี่เป็นประโยชน์เมื่อจัดการกลุ่มจับจำนวนมากโดยเฉพาะหรือสตริงที่มีขนาดใหญ่มาก แต่ถ้าคุณต้องการผลลัพธ์สามารถเปลี่ยนเป็น Array ได้อย่างง่ายดายโดยใช้ไวยากรณ์การแพร่กระจายหรือArray.fromวิธีการ:

function getFirstGroup(regexp, str) {
  const array = [...str.matchAll(regexp)];
  return array.map(m => m[1]);
}

// or:
function getFirstGroup(regexp, str) {
  return Array.from(str.matchAll(regexp), m => m[1]);
}

ในขณะเดียวกันในขณะที่ข้อเสนอนี้ได้รับการสนับสนุนที่กว้างมากขึ้นคุณสามารถใช้แพคเกจชิมอย่างเป็นทางการ

นอกจากนี้การทำงานภายในของวิธีการก็ง่าย การใช้งานที่เทียบเท่าโดยใช้ฟังก์ชั่นเครื่องกำเนิดไฟฟ้าจะเป็นดังนี้:

function* matchAll(str, regexp) {
  const flags = regexp.global ? regexp.flags : regexp.flags + "g";
  const re = new RegExp(regexp, flags);
  let match;
  while (match = re.exec(str)) {
    yield match;
  }
}

สำเนาของ regexp ต้นฉบับถูกสร้างขึ้น; นี่คือการหลีกเลี่ยงผลข้างเคียงเนื่องจากการกลายพันธุ์ของlastIndexคุณสมบัติเมื่อต้องผ่านการแข่งขันหลายครั้ง

นอกจากนี้เราต้องให้แน่ใจว่า regexp มีธงทั่วโลกเพื่อหลีกเลี่ยงการวนซ้ำไม่สิ้นสุด

ผมยังมีความสุขที่จะเห็นว่าแม้กระทั่งคำถามนี้ StackOverflow ได้รับการอ้างอิงในการอภิปรายของข้อเสนอ


114
+1 โปรดทราบว่าในตัวอย่างที่สองคุณควรใช้วัตถุ RegExp (ไม่เพียง "/ myregexp /") เพราะมันจะเก็บค่า lastIndex ในวัตถุ โดยไม่ใช้ออบเจ็กต์ Regexp มันจะวนซ้ำอย่างไม่มีที่สิ้นสุด
ianaz

7
@ianaz: ฉันไม่เชื่อว่า 'เป็นจริงเหรอ? http://jsfiddle.net/weEg9/ดูเหมือนว่าจะทำงานกับ Chrome ได้อย่างน้อย
Spinningarrow

16
ทำไมทำข้างต้นแทน: var match = myString.match(myRegexp); // alert(match[1])?
JohnAllen

29
ไม่จำเป็นต้องชัดเจน "new RegExp" อย่างชัดเจนอย่างไรก็ตามการวนซ้ำไม่สิ้นสุดจะเกิดขึ้นถ้าไม่ได้ระบุ / g
George C

4
อีกวิธีหนึ่งที่จะไม่วิ่งเข้าไปในวงวนไม่สิ้นสุดก็คือการอัพเดตสตริงอย่างชัดเจนเช่นstring = string.substring(match.index + match[0].length)
Olga

186

นี่คือวิธีการที่คุณสามารถใช้เพื่อให้ได้กลุ่มการจับภาพที่nสำหรับการแข่งขันแต่ละครั้ง:

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


12
นี่เป็นคำตอบที่เหนือกว่าสำหรับคนอื่น ๆ เพราะมันแสดงให้เห็นอย่างถูกต้องมากกว่าการแข่งขันทั้งหมดแทนที่จะได้รับเพียงครั้งเดียว
Rob Evans

13
mnn ถูกต้อง สิ่งนี้จะสร้างการวนซ้ำไม่สิ้นสุดหากไม่มีการตั้งค่าสถานะ 'g' ระวังด้วยฟังก์ชั่นนี้
Druska

4
ฉันปรับปรุงสิ่งนี้เพื่อให้คล้ายกับ python re.findall () มันจัดกลุ่มการแข่งขันทั้งหมดเป็นอาร์เรย์ของอาร์เรย์ นอกจากนี้ยังแก้ไขปัญหาการวนรอบไม่สิ้นสุดของตัวแก้ไขโกลบอล jsfiddle.net/ravishi/MbwpV
ravishi

5
@MichaelMikowski ตอนนี้คุณเพิ่งซ่อนวงวนไม่สิ้นสุดของคุณ แต่รหัสของคุณจะทำงานช้า ฉันขอยืนยันว่าดีกว่าที่จะมีการทำลายโค้ดในทางที่ไม่ดีดังนั้นคุณจึงจับมันได้ในการพัฒนา การทำซ้ำซ้ำ bs สูงสุดบางอย่างนั้นไม่เป็นระเบียบ การซ่อนปัญหาแทนที่จะแก้ไขสาเหตุที่แท้จริงไม่ใช่คำตอบ
wallacer

4
@MichaelMikowski ที่ไม่ได้หมายถึงช้าลงเมื่อคุณไม่ได้กดขีด จำกัด การดำเนินการ เมื่อคุณอยู่มันชัดเจนว่าช้ากว่ามาก ฉันไม่ได้บอกว่ารหัสของคุณใช้งานไม่ได้ฉันกำลังบอกว่าในทางปฏิบัติฉันคิดว่ามันจะทำให้เกิดอันตรายมากกว่าดี ผู้ที่ทำงานในสภาพแวดล้อมแบบ dev จะเห็นโค้ดทำงานได้ดีภายใต้การไม่โหลดแม้จะมีการประมวลผลที่ไม่จำเป็น 10,000 ชิ้นของโค้ด จากนั้นพวกเขาจะผลักมันออกไปสู่สภาพแวดล้อมที่ใช้งานจริงและสงสัยว่าทำไมแอปของพวกเขาถึงโหลด จากประสบการณ์ของฉันจะดีกว่าถ้าสิ่งต่าง ๆ แตกต่างกันอย่างชัดเจนและก่อนหน้านี้ในวงจรการพัฒนา
wallacer

58

var myString = "something format_abc";
var arr = myString.match(/\bformat_(.*?)\b/);
console.log(arr[0] + " " + arr[1]);

\bไม่ได้เป็นสิ่งเดียวกัน (ใช้งานได้--format_foo/แต่ไม่ทำงานformat_a_b) แต่ฉันต้องการแสดงทางเลือกให้กับการแสดงออกของคุณซึ่งไม่เป็นไร แน่นอนการmatchโทรเป็นสิ่งสำคัญ


2
มันตรงกันข้ามอย่างแน่นอน '\ b' คั่นคำ word = '\ w' = [a-zA-Z0-9_] "format_a_b" เป็นคำ
BF

1
@BFHonestly ฉันเพิ่ม "ไม่ทำงานformat_a_b" เป็นความคิดหลังจาก 6 ปีที่แล้วและฉันจำไม่ได้ว่าสิ่งที่ฉันหมายถึงที่นั่น ... :-) ฉันคิดว่ามันหมายความว่า "ไม่ทำงานเพื่อจับภาพaเท่านั้น" กล่าวคือ format_ส่วนที่ตัวอักษรแรกหลังจาก
PhiLho

1
ฉันอยากจะบอกว่า \ b (- format_foo /} \ b ไม่ส่งคืน "--format_foo /" เพราะ "-" และ "/" ไม่ใช่อักขระ \ word แต่ \ b (format_a_b) \ b กลับมา "format_a_b ." ตอนผมหมายถึงคำสั่งข้อความของคุณในวงเล็บรอบ (ไม่ไม่มีการโหวตลง!).
BF

31

ในส่วนที่เกี่ยวกับตัวอย่างวงเล็บหลายคู่ด้านบนฉันกำลังมองหาคำตอบที่นี่หลังจากไม่ได้รับสิ่งที่ฉันต้องการจาก:

var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);

หลังจากดูฟังก์ชั่นที่ซับซ้อนเล็กน้อยแล้วเรียกว่า while และ. พุช () ด้านบนมันเริ่มขึ้นเมื่อฉันว่าปัญหาสามารถแก้ไขได้อย่างหรูหราด้วย mystring.replace () แทน (การแทนที่ไม่ใช่จุดและไม่ได้ทำ CLEAN ตัวเลือกการเรียกใช้ฟังก์ชันเรียกซ้ำในตัวสำหรับพารามิเตอร์ที่สองคือ!):

var yourstring = 'something format_abc something format_def something format_ghi';

var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );

หลังจากนี้ฉันไม่คิดว่าฉันจะใช้. match () เพื่อทำอะไรอีกเลย


26

สุดท้าย แต่ไม่ท้ายสุดฉันพบโค้ดหนึ่งบรรทัดที่ทำงานได้ดีสำหรับฉัน (JS ES6):

let reg = /#([\S]+)/igm; // Get hashtags.
let string = 'mi alegría es total! ✌🙌\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';

let matches = (string.match(reg) || []).map(e => e.replace(reg, '$1'));
console.log(matches);

สิ่งนี้จะส่งคืน:

['fiestasdefindeaño', 'PadreHijo', 'buenosmomentos', 'france', 'paris']

1
BOOM! นั่นเป็นทางออกที่สวยงามมากที่สุดที่นี่ ฉันพบว่าสิ่งนี้ดีกว่าวิธีการแบบเต็มรูปแบบของ Alexz เพราะวิธีนี้ดูน้อยกว่าหน้าและมีความสง่างามสำหรับผลลัพธ์หลายรายการ ทำได้ดีมากในเรื่องนี้ Sebastien H.replace
Cody

นี้ทำงานได้เป็นอย่างดีว่ามันแน่นอนที่จะเข้าสู่ utils ของฉัน :)
โค

1
@Cody ฮ่าฮ่าขอบคุณชาย!
Sebastien H.

19

คำศัพท์ที่ใช้ในคำตอบนี้:

  • การแข่งขันแสดงให้เห็นผลของการใช้รูปแบบของคุณกับ RegEx someString.match(regexPattern)สตริงของคุณเช่นดังนั้น:
  • รูปแบบที่จับคู่จะระบุส่วนที่ตรงกันทั้งหมดของสตริงอินพุตซึ่งทั้งหมดอยู่ภายในอาร์เรย์จับคู่ นี่คืออินสแตนซ์ทั้งหมดของรูปแบบของคุณภายในสตริงอินพุต
  • กลุ่มที่จับคู่ระบุว่าทุกกลุ่มที่จะจับได้ถูกกำหนดในรูปแบบ RegEx (รูปแบบในวงเล็บเช่นดังนั้น: /format_(.*?)/gซึ่ง(.*?)จะเป็นกลุ่มที่จับคู่.) เหล่านี้อาศัยอยู่ภายในรูปแบบการจับคู่

ลักษณะ

ที่จะได้รับการเข้าถึงกลุ่มจับคู่ในแต่ละรูปแบบการจับคู่คุณต้องมีฟังก์ชั่นหรือสิ่งที่คล้ายกับย้ำในช่วงการแข่งขัน มีหลายวิธีที่คุณสามารถทำได้เช่นเดียวกับคำตอบอื่น ๆ ที่แสดง คำตอบอื่น ๆ ส่วนใหญ่ใช้การวนรอบสักครู่เพื่อวนซ้ำทุกรูปแบบที่ตรงกันแต่ฉันคิดว่าเราทุกคนรู้ถึงอันตรายที่อาจเกิดขึ้นจากวิธีการนั้น มีความจำเป็นต้องจับคู่กับรูปแบบnew RegExp()แทนที่จะเป็นเพียงรูปแบบตัวเองซึ่งได้กล่าวถึงในความคิดเห็นเท่านั้น นี่เป็นเพราะ.exec()วิธีการทำงานคล้ายกับฟังก์ชั่นเครื่องกำเนิดไฟฟ้า - มันหยุดทุกครั้งที่มีการแข่งขันแต่.lastIndexยังคงที่จะดำเนินการต่อจากที่นั่นในการ.exec()โทรครั้งต่อไป

ตัวอย่างรหัส

ด้านล่างนี้เป็นตัวอย่างของฟังก์ชันsearchStringที่คืนค่ารูปแบบที่ตรงกันArrayทั้งหมดโดยที่แต่ละรายการจะมีกลุ่มที่จับคู่ทั้งหมดที่มีอยู่ แทนที่จะใช้ a while loop ฉันได้ให้ตัวอย่างโดยใช้ทั้งฟังก์ชั่นและวิธีที่มีประสิทธิภาพมากขึ้นโดยใช้ลูปธรรมดาmatchArrayArray.prototype.map()for

รุ่นที่รัดกุม (รหัสน้อยกว่าน้ำตาลประโยคมากขึ้น)

สิ่งเหล่านี้มีประสิทธิภาพน้อยกว่าเนื่องจากใช้forEach-loop แทนการfor-loop ที่เร็วขึ้น

// Concise ES6/ES2015 syntax
const searchString = 
    (string, pattern) => 
        string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match => 
            new RegExp(pattern.source, pattern.flags)
            .exec(match));

// Or if you will, with ES5 syntax
function searchString(string, pattern) {
    return string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match =>
            new RegExp(pattern.source, pattern.flags)
            .exec(match));
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

เวอร์ชั่นนักแสดง (รหัสเพิ่มเติม, น้ำตาลน้อยกว่าวากยสัมพันธ์)

// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
    let result = [];

    const matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (let i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
};

// Same thing, but with ES5 syntax
function searchString(string, pattern) {
    var result = [];

    var matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (var i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

ฉันยังไม่ได้เปรียบเทียบทางเลือกเหล่านี้กับที่กล่าวถึงก่อนหน้านี้ในคำตอบอื่น ๆ แต่ฉันสงสัยว่าวิธีการนี้มีประสิทธิภาพน้อยกว่าและไม่ปลอดภัยน้อยกว่าวิธีอื่น


19

String#matchAll(ดูร่างข้อเสนอขั้นที่ 3/7 ธันวาคม 2018 ) ลดความซับซ้อนของ acccess ให้กับทุกกลุ่มในออบเจ็กต์การจับคู่ (จำไว้ว่ากลุ่มที่ 0 เป็นคู่ที่ตรงกันทั้งหมดในขณะที่กลุ่มอื่น ๆ

ด้วยmatchAllสามารถใช้ได้คุณสามารถหลีกเลี่ยงwhileห่วงและexecมี/g... แต่โดยใช้matchAllคุณจะได้รับกลับ iterator ซึ่งคุณสามารถใช้กับความสะดวกมากขึ้นfor...of, อาร์เรย์การแพร่กระจายหรือArray.from()โครงสร้าง

วิธีนี้ให้ผลคล้ายกับRegex.Matchesใน C # re.finditerใน Python preg_match_allใน PHP

ดูตัวอย่างของ JS (ทดสอบใน Google Chrome 73.0.3683.67 (รุ่นเป็นทางการ), เบต้า (64- บิต)):

var myString = "key1:value1, key2-value2!!@key3=value3";
var matches = myString.matchAll(/(\w+)[:=-](\w+)/g);
console.log([...matches]); // All match with capturing group values

การconsole.log([...matches])แสดง

ป้อนคำอธิบายรูปภาพที่นี่

นอกจากนี้คุณยังอาจได้รับค่าการจับคู่หรือค่ากลุ่มเฉพาะที่ใช้

let matchData = "key1:value1, key2-value2!!@key3=value3".matchAll(/(\w+)[:=-](\w+)/g)
var matches = [...matchData]; // Note matchAll result is not re-iterable

console.log(Array.from(matches, m => m[0])); // All match (Group 0) values
// => [ "key1:value1", "key2-value2", "key3=value3" ]
console.log(Array.from(matches, m => m[1])); // All match (Group 1) values
// => [ "key1", "key2", "key3" ]

หมายเหตุ : ดูรายละเอียดความเข้ากันได้ของเบราว์เซอร์


ตัวอย่างที่สมบูรณ์แบบสำหรับคู่ของค่าคีย์ กระชับและอ่านง่ายใช้งานง่ายมาก นอกจากนี้การจัดการข้อผิดพลาดที่ดีกว่าการแพร่กระจายจะส่งกลับอาร์เรย์ที่ว่างเปล่ามากกว่า null ดังนั้นจึงไม่มีข้อผิดพลาดไม่มีคุณสมบัติ "ความยาว" เป็นโมฆะ '
Jarrod McGuire

17

ไวยากรณ์ของคุณอาจไม่ดีที่สุดในการรักษา FF / Gecko กำหนด RegExp เป็นส่วนขยายของ Function
(FF2 ไปไกลเท่าที่typeof(/pattern/) == 'function')

ดูเหมือนว่านี่เป็นสิ่งที่เฉพาะเจาะจงสำหรับ FF - IE, Opera และ Chrome ทั้งหมดยกเว้นข้อยกเว้น

แต่ใช้วิธีการอย่างใดอย่างหนึ่งที่กล่าวถึงก่อนหน้านี้โดยผู้อื่น: หรือRegExp#exec พวกเขาให้ผลลัพธ์เดียวกัน:String#match

var regex = /(?:^|\s)format_(.*?)(?:\s|$)/;
var input = "something format_abc";

regex(input);        //=> [" format_abc", "abc"]
regex.exec(input);   //=> [" format_abc", "abc"]
input.match(regex);  //=> [" format_abc", "abc"]

16

ไม่จำเป็นต้องเรียกใช้execเมธอด! คุณสามารถใช้วิธี "จับคู่" โดยตรงบนสตริง อย่าลืมวงเล็บ

var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...

ตำแหน่ง 0 มีสตริงพร้อมผลลัพธ์ทั้งหมด ตำแหน่งที่ 1 มีคู่แรกที่แสดงด้วยวงเล็บและตำแหน่งที่ 2 มีคู่ที่แยกจากกันในวงเล็บของคุณ วงเล็บที่ซ้อนกันนั้นมีความซับซ้อนดังนั้นระวัง!


4
หากไม่มีการตั้งค่าสถานะส่วนกลางสิ่งนี้จะส่งคืนการแข่งขันทั้งหมดด้วยคุณจะได้รับหนึ่งรายการใหญ่ดังนั้นโปรดระวัง
Shadymilkman01

8

ซับหนึ่งที่ใช้งานได้เฉพาะในกรณีที่คุณมีวงเล็บคู่เดียว:

while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};

4
ทำไมไม่while (match = myRegex.exec(myStr)) matches.push(match[1])
willlma


7

ด้วย es2018 คุณสามารถString.match()ใช้กลุ่มที่มีชื่อได้ทำให้ regex ของคุณชัดเจนยิ่งขึ้นว่ามันพยายามทำอะไร

const url =
  '/programming/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression?some=parameter';
const regex = /(?<protocol>https?):\/\/(?<hostname>[\w-\.]*)\/(?<pathname>[\w-\./]+)\??(?<querystring>.*?)?$/;
const { groups: segments } = url.match(regex);
console.log(segments);

และคุณจะได้รับสิ่งที่ชอบ

{โปรโตคอล: "https", ชื่อโฮสต์: "stackoverflow.com", ชื่อพา ธ : "คำถาม / 432493 / วิธีทำคุณเข้าถึงการจับคู่กลุ่มในรูปแบบ javascript-regular-expression", querystring: " บางพารามิเตอร์ = "}


6

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


3

รหัสของคุณใช้งานได้สำหรับฉัน (FF3 บน Mac) แม้ว่าฉันจะเห็นด้วยกับPhiLoว่า regex น่าจะเป็น:

/\bformat_(.*?)\b/

(แต่แน่นอนฉันไม่แน่ใจเพราะฉันไม่ทราบบริบทของ regex)


1
เป็นรายการที่คั่นด้วยช่องว่างดังนั้นฉันจึงคิดว่า \ s จะไม่เป็นไร แปลกว่ารหัสที่ไม่ทำงานสำหรับฉัน (FF3 Vista)
nickf

1
ใช่แปลกอย่างแท้จริง คุณลองด้วยตัวเองในคอนโซล Firebug หรือไม่? ฉันหมายถึงจากหน้าที่ว่างเปล่าเป็นอย่างอื่น
PEZ

2
/*Regex function for extracting object from "window.location.search" string.
 */

var search = "?a=3&b=4&c=7"; // Example search string

var getSearchObj = function (searchString) {

    var match, key, value, obj = {};
    var pattern = /(\w+)=(\w+)/g;
    var search = searchString.substr(1); // Remove '?'

    while (match = pattern.exec(search)) {
        obj[match[0].split('=')[0]] = match[0].split('=')[1];
    }

    return obj;

};

console.log(getSearchObj(search));

2

คุณไม่จำเป็นต้องวนซ้ำอย่างชัดเจนเพื่อแยกวิเคราะห์การแข่งขันหลายรายการ - ผ่านฟังก์ชันการแทนที่เป็นอาร์กิวเมนต์ที่สองตามที่อธิบายไว้ในString.prototype.replace(regex, func):

var str = "Our chief weapon is {1}, {0} and {2}!"; 
var params= ['surprise', 'fear', 'ruthless efficiency'];
var patt = /{([^}]+)}/g;

str=str.replace(patt, function(m0, m1, position){return params[parseInt(m1)];});

document.write(str);

m0อาร์กิวเมนต์หมายถึง substring จับคู่เต็มรูปแบบ{0}, {1}ฯลฯm1หมายถึงกลุ่มแรกที่ตรงกันคือส่วนหนึ่งในวงเล็บใน regex ซึ่งเป็น0สำหรับการแข่งขันครั้งแรก และpositionเป็นดัชนีเริ่มต้นภายในสตริงที่พบกลุ่มการจับคู่ - ไม่ได้ใช้ในกรณีนี้


1

เราสามารถเข้าถึงกลุ่มที่ตรงกันในนิพจน์ทั่วไปโดยใช้เครื่องหมายแบ็กสแลชตามด้วยหมายเลขของกลุ่มที่ตรงกัน:

/([a-z])\1/

ในรหัส \ 1 แสดงถึงการจับคู่โดยกลุ่มแรก ([az])


1

โซลูชันเดียว:

const matches = (text,regex) => [...text.matchAll(regex)].map(([match])=>match)

ดังนั้นคุณสามารถใช้วิธีนี้ (ต้องใช้ / g):

matches("something format_abc", /(?:^|\s)format_(.*?)(?:\s|$)/g)

ผลลัพธ์:

[" format_abc"]


0

ฉันเป็นเหมือนฉันและหวังว่า regex จะส่งคืนวัตถุเช่นนี้:

{
    match: '...',
    matchAtIndex: 0,
    capturedGroups: [ '...', '...' ]
}

จากนั้นตัดฟังก์ชั่นจากด้านล่าง

/**
 * @param {string | number} input
 *          The input string to match
 * @param {regex | string}  expression
 *          Regular expression 
 * @param {string} flags
 *          Optional Flags
 * 
 * @returns {array}
 * [{
    match: '...',
    matchAtIndex: 0,
    capturedGroups: [ '...', '...' ]
  }]     
 */
function regexMatch(input, expression, flags = "g") {
  let regex = expression instanceof RegExp ? expression : new RegExp(expression, flags)
  let matches = input.matchAll(regex)
  matches = [...matches]
  return matches.map(item => {
    return {
      match: item[0],
      matchAtIndex: item.index,
      capturedGroups: item.length > 1 ? item.slice(1) : undefined
    }
  })
}

let input = "key1:value1, key2:value2 "
let regex = /(\w+):(\w+)/g

let matches = regexMatch(input, regex)

console.log(matches)


0

เพียงใช้ RegExp $ 1 ... กลุ่มที่ $ n เช่น:

1. จับคู่ RegExp กลุ่มที่ 1 $ 1

  1. เพื่อให้ตรงกับกลุ่มที่ 2 RegExp. $ 2

ถ้าคุณใช้ 3 กลุ่มใน regex likey (ใช้ note หลัง string.match (regex))

RegExp. $ 1 RegExp. $ 2 RegExp. $ 3

 var str = "The rain in ${india} stays safe"; 
  var res = str.match(/\${(.*?)\}/ig);
  //i used only one group in above example so RegExp.$1
console.log(RegExp.$1)

//easiest way is use RegExp.$1 1st group in regex and 2nd grounp like
 //RegExp.$2 if exist use after match

var regex=/\${(.*?)\}/ig;
var str = "The rain in ${SPAIN} stays ${mainly} in the plain"; 
  var res = str.match(regex);
for (const match of res) {
  var res = match.match(regex);
  console.log(match);
  console.log(RegExp.$1)
 
}

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