ส่งคืนตำแหน่งของการจับคู่ regex () ใน Javascript หรือไม่


154

มีวิธีในการดึงข้อมูลตำแหน่งตัวอักษร (เริ่มต้น) ภายในสตริงของผลลัพธ์ของการจับคู่ regex () ใน Javascript หรือไม่?

คำตอบ:


225

execส่งคืนวัตถุที่มีindexคุณสมบัติ:

var match = /bar/.exec("foobar");
if (match) {
    console.log("match found at " + match.index);
}

และสำหรับการแข่งขันหลายรายการ:

var re = /bar/g,
    str = "foobarfoobar";
while ((match = re.exec(str)) != null) {
    console.log("match found at " + match.index);
}


5
ขอบคุณสำหรับความช่วยเหลือของคุณ! คุณสามารถบอกฉันด้วยฉันจะหาดัชนีของการแข่งขันหลายรายการได้อย่างไร
stagas

9
หมายเหตุ: การใช้reตัวแปรเป็นตัวและการเพิ่มgตัวดัดแปลงมีความสำคัญมาก! มิฉะนั้นคุณจะได้รับการวนซ้ำไม่รู้จบ
oriadam

1
@ OnurYıldırım - นี่คือ jsfiddle ของมันทำงานได้ ... ฉันได้ทดสอบทุกอย่างกลับไปที่ IE5 ... ใช้งานได้ดี: jsfiddle.net/6uwn1vof
Jimbo Jonny

1
@JimboJonny อืมฉันเรียนรู้สิ่งใหม่แล้ว กรณีทดสอบของฉันกลับundefinedมา jsfiddle.net/6uwn1vof/2 ซึ่งไม่ใช่ตัวอย่างเช่นการค้นหาเช่นคุณ
Onur Yıldırım

1
@ OnurYıldırım - ลบการgตั้งค่าสถานะและจะใช้งานได้ เนื่องจากmatchเป็นฟังก์ชันของสตริงไม่ใช่ regex ที่ไม่สามารถเป็น stateful ได้execดังนั้นจึงให้ถือว่าเป็นเท่านั้นexec(เช่นมีคุณสมบัติ index) หากคุณไม่ได้มองหาการแข่งขันระดับโลก ... เพราะ statefulness ไม่สำคัญ .
Jimbo Jonny

60

นี่คือสิ่งที่ฉันมาด้วย:

// Finds starting and ending positions of quoted text
// in double or single quotes with escape char support like \" \'
var str = "this is a \"quoted\" string as you can 'read'";

var patt = /'((?:\\.|[^'])*)'|"((?:\\.|[^"])*)"/igm;

while (match = patt.exec(str)) {
  console.log(match.index + ' ' + patt.lastIndex);
}


18
match.index + match[0].lengthยังใช้งานได้สำหรับตำแหน่งสุดท้าย
Beni Cherniavsky-Paskin


1
@ BeniCherniavsky-Paskin ตำแหน่งสุดท้ายจะmatch.index + match[0].length - 1ไม่ใช่เหรอ?
David

1
@ David, ฉันหมายถึงตำแหน่งที่สิ้นสุด แต่เพียงผู้เดียวในขณะที่การดำเนินการเช่นโดยการและ.slice() .substring()การสิ้นสุดแบบรวมจะน้อยกว่าที่คุณพูด 1 (ระวังว่าการรวมมักจะหมายถึงดัชนีของการแข่งขันครั้งสุดท้ายภายในเว้นแต่เป็นการแข่งขันที่ว่างเปล่าซึ่งเป็น 1 ก่อนการแข่งขันและอาจจะ-1อยู่นอกสตริงทั้งหมดสำหรับการแข่งขันที่ว่างเปล่าที่เริ่มต้น ... )
Beni Cherniavsky-Paskin

16

จากdeveloper.mozilla.orgเอกสารเกี่ยวกับ.match()วิธีการสตริง:

Array ที่ส่งคืนมีคุณสมบัติอินพุตเพิ่มเติมซึ่งมีสตริงต้นฉบับที่ถูกวิเคราะห์คำ นอกจากนี้มันยังมีคุณสมบัติดัชนีซึ่งหมายถึงดัชนี zero-based ของการแข่งขันในสตริง

เมื่อจัดการกับ regex ที่ไม่เป็นสากล (เช่นไม่มีgแฟล็กบน regex ของคุณ) ค่าที่ส่งคืนโดย.match()มีindexคุณสมบัติ ... สิ่งที่คุณต้องทำคือเข้าถึง

var index = str.match(/regex/).index;

นี่คือตัวอย่างที่แสดงว่ามันทำงานได้ดี:

var str = 'my string here';

var index = str.match(/here/).index;

alert(index); // <- 10

ฉันได้ทำการทดสอบวิธีนี้ไปจนถึง IE5 เรียบร้อยแล้ว


6

คุณสามารถใช้searchวิธีการของStringวัตถุ สิ่งนี้จะใช้ได้กับคู่แรกเท่านั้น แต่จะทำในสิ่งที่คุณอธิบาย ตัวอย่างเช่น:

"How are you?".search(/are/);
// 4

6

นี่คือคุณสมบัติที่ยอดเยี่ยมที่ฉันค้นพบเมื่อเร็ว ๆ นี้ฉันลองสิ่งนี้บนคอนโซลและดูเหมือนว่าจะใช้งานได้:

var text = "border-bottom-left-radius";

var newText = text.replace(/-/g,function(match, index){
    return " " + index + " ";
});

ซึ่งส่งคืน: "เส้นขอบ 6 ด้านล่าง 13 ด้านซ้าย 18 รัศมี"

ดังนั้นนี่คือสิ่งที่คุณกำลังมองหา


6
เพียงแค่ระวังว่าฟังก์ชั่นการเปลี่ยนเพิ่มกลุ่มการดักจับด้วยดังนั้นโปรดทราบว่ามันเป็นรายการที่สองถึงครั้งสุดท้ายเสมอในฟังก์ชั่นการเปลี่ยนargumentsที่เป็นตำแหน่ง ไม่ใช่ "อาร์กิวเมนต์ที่สอง" อาร์กิวเมนต์ของฟังก์ชันคือ "การจับคู่แบบเต็มกลุ่ม 1, กลุ่ม 2, .... , ดัชนีการจับคู่, สตริงเต็มรูปแบบที่ตรงกับ"
Mike 'Pomax' Kamermans

2

ในเบราว์เซอร์สมัยใหม่คุณสามารถทำสิ่งนี้ได้ด้วยstring.matchAll ()()

ประโยชน์กับวิธีการนี้ครับRegExp.exec()คือว่ามันไม่ได้ขึ้นอยู่กับ regex เป็น stateful ในขณะที่@ คำตอบของต้นกระเจี๊ยบ

let regexp = /bar/g;
let str = 'foobarfoobar';

let matches = [...str.matchAll(regexp)];
matches.forEach((match) => {
    console.log("match found at " + match.index);
});


1

สมาชิกนี้ fn ส่งกลับอาร์เรย์ของตำแหน่งตาม 0 ถ้ามีของคำอินพุตภายในวัตถุ String

String.prototype.matching_positions = function( _word, _case_sensitive, _whole_words, _multiline )
{
   /*besides '_word' param, others are flags (0|1)*/
   var _match_pattern = "g"+(_case_sensitive?"i":"")+(_multiline?"m":"") ;
   var _bound = _whole_words ? "\\b" : "" ;
   var _re = new RegExp( _bound+_word+_bound, _match_pattern );
   var _pos = [], _chunk, _index = 0 ;

   while( true )
   {
      _chunk = _re.exec( this ) ;
      if ( _chunk == null ) break ;
      _pos.push( _chunk['index'] ) ;
      _re.lastIndex = _chunk['index']+1 ;
   }

   return _pos ;
}

ตอนนี้ลอง

var _sentence = "What do doers want ? What do doers need ?" ;
var _word = "do" ;
console.log( _sentence.matching_positions( _word, 1, 0, 0 ) );
console.log( _sentence.matching_positions( _word, 1, 1, 0 ) );

นอกจากนี้คุณยังสามารถป้อนการแสดงออกปกติ:

var _second = "z^2+2z-1" ;
console.log( _second.matching_positions( "[0-9]\z+", 0, 0, 0 ) );

ที่นี่หนึ่งได้รับดัชนีตำแหน่งของคำเชิงเส้น


1
var str = "The rain in SPAIN stays mainly in the plain";

function searchIndex(str, searchValue, isCaseSensitive) {
  var modifiers = isCaseSensitive ? 'gi' : 'g';
  var regExpValue = new RegExp(searchValue, modifiers);
  var matches = [];
  var startIndex = 0;
  var arr = str.match(regExpValue);

  [].forEach.call(arr, function(element) {
    startIndex = str.indexOf(element, startIndex);
    matches.push(startIndex++);
  });

  return matches;
}

console.log(searchIndex(str, 'ain', true));

สิ่งนี้ไม่ถูกต้อง str.indexOfนี่เป็นเพียงการค้นหาข้อความที่เกิดขึ้นในการจับคู่ครั้งต่อไปซึ่งไม่จำเป็นต้องตรงกับ JS regex รองรับเงื่อนไขข้อความนอกการจับภาพด้วย lookahead ยกตัวอย่างเช่นsearchIndex("foobarfoobaz", "foo(?=baz)", true)ควรจะให้ไม่ได้[6] [0]
rakslice

ทำไม `[] .forEach.call (arr, ฟังก์ชั่น (องค์ประกอบ)` ทำไมไม่ arr.forEach หรือ arr.map
Ankit Kumar

-1
function trimRegex(str, regex){
    return str.substr(str.match(regex).index).split('').reverse().join('').substr(str.match(regex).index).split('').reverse().join('');
}

let test = '||ab||cd||';
trimRegex(test, /[^|]/);
console.log(test); //output: ab||cd

หรือ

function trimChar(str, trim, req){
    let regex = new RegExp('[^'+trim+']');
    return str.substr(str.match(regex).index).split('').reverse().join('').substr(str.match(regex).index).split('').reverse().join('');
}

let test = '||ab||cd||';
trimChar(test, '|');
console.log(test); //output: ab||cd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.