Trả về vị trí của một trận đấu regex () trong Javascript?


154

Có cách nào để truy xuất các vị trí ký tự (bắt đầu) bên trong chuỗi kết quả của kết quả khớp chính tả () trong Javascript không?

Câu trả lời:


225

exectrả về một đối tượng có thuộc indextính:

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

Và cho nhiều trận đấu:

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


5
Cảm ơn bạn đã giúp đỡ! Bạn có thể cho tôi biết làm thế nào để tôi tìm thấy các chỉ mục của nhiều trận đấu?
stagas

9
Lưu ý: sử dụng renhư một biến và thêm công cụ gsửa đổi đều rất quan trọng! Nếu không bạn sẽ có được một vòng lặp vô tận.
oriadam

1
@ OnurYıldırım - đây là một jsfiddle của nó hoạt động ... Tôi đã thử nghiệm tất cả các cách trở lại IE5 ... hoạt động rất tốt: jsfiddle.net/6uwn1vof
Jimbo Jonny

1
@JimboJonny, hm tôi đã học được một điều mới. Trường hợp thử nghiệm của tôi trở lại undefined. jsfiddle.net/6uwn1vof/2 không phải là một ví dụ giống như tìm kiếm như của bạn.
Onur Yıldırım

1
@ OnurYıldırım - Xóa gcờ và nó sẽ hoạt động. Vì matchlà một hàm của chuỗi, không phải là regex nên nó không thể là trạng thái như execvậy, vì vậy nó chỉ xử lý nó như exec(nghĩa là có thuộc tính chỉ mục) nếu bạn không tìm kiếm một kết quả khớp toàn cầu ... bởi vì tính trạng thái không quan trọng .
Jimbo Jonny

60

Đây là những gì tôi nghĩ ra:

// 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].lengthcũng hoạt động cho vị trí cuối.
Beni Cherniavsky-Paskin

thực sự tốt đẹp - so sánh ở đây
Louis Maddox

1
@ BeniCéciavsky-Paskin, vị trí cuối sẽ là match.index + match[0].length - 1gì?
David

1
@David, ý tôi là vị trí cuối độc quyền, như được lấy ví dụ bởi .slice().substring(). Kết thúc bao gồm sẽ là 1 ít hơn như bạn nói. (Hãy cẩn thận rằng đã bao gồm thường có nghĩa là chỉ số của char cuối cùng trong trận đấu, trừ khi đó là một trận đấu có sản phẩm nào trong đó đã ghi bàn 1 trước khi trận đấu và có thể là -1bên ngoài chuỗi hoàn toàn cho trận đấu trống ở đầu ...)
Beni Cherniavsky-Paskin

16

Từ tài liệu developer.mozilla.org trên .match()phương thức String :

Mảng được trả về có một thuộc tính đầu vào bổ sung, chứa chuỗi gốc được phân tích cú pháp. Ngoài ra, nó có một thuộc tính chỉ mục, đại diện cho chỉ số dựa trên không của trận đấu trong chuỗi .

Khi giao dịch với regex không toàn cầu (nghĩa là không có gcờ trên regex của bạn), giá trị được trả về .match()có một thuộc indextính ... tất cả những gì bạn phải làm là truy cập vào nó.

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

Đây là một ví dụ cho thấy nó hoạt động tốt:

var str = 'my string here';

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

alert(index); // <- 10

Tôi đã thử nghiệm thành công tất cả các cách trở lại IE5.


6

Bạn có thể sử dụng searchphương thức của Stringđối tượng. Điều này sẽ chỉ hoạt động cho trận đấu đầu tiên, nhưng nếu không sẽ làm những gì bạn mô tả. Ví dụ:

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

6

Đây là một tính năng thú vị mà tôi phát hiện ra gần đây, tôi đã thử nó trên bảng điều khiển và nó dường như hoạt động:

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

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

Mà trả về: "viền 6 đáy 13 bán kính 18 trái"

Vì vậy, đây dường như là những gì bạn đang tìm kiếm.


6
chỉ cần lưu ý rằng các chức năng thay thế cũng thêm các nhóm chụp, vì vậy hãy lưu ý rằng đó luôn là mục nhập thứ hai đến cuối cùng trong chức năng thay thế argumentsđó là vị trí. Không phải "đối số thứ hai". Các đối số chức năng là "kết hợp đầy đủ, nhóm1, nhóm2, ...., chỉ số khớp, chuỗi đầy đủ khớp với"
Mike 'Pomax' Kamermans

1

Thành viên fn này trả về một mảng các vị trí dựa trên 0, nếu có, của từ đầu vào bên trong đối tượng 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 ;
}

Bây giờ cố gắng

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 ) );

Bạn cũng có thể nhập biểu thức thông thường:

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

Ở đây người ta có được chỉ số vị trí của thuật ngữ tuyến tính.


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));

Điều này là không đúng. str.indexOfỞ đây chỉ tìm thấy sự xuất hiện tiếp theo của văn bản được bắt bởi trận đấu, mà không nhất thiết là trận đấu. Regex JS hỗ trợ các điều kiện trên văn bản bên ngoài bản chụp với giao diện. Chẳng hạn searchIndex("foobarfoobaz", "foo(?=baz)", true)nên cho [6], không [0].
rakslice

why `[] .forEach.call (mảng, hàm (phần tử)` why not Array.forEach hoặc Array.map
Ankit Kumar

1

Trong các trình duyệt hiện đại, bạn có thể thực hiện việc này với string.matchAll () .

Lợi ích của phương pháp này so với phương pháp RegExp.exec()này là nó không phụ thuộc vào biểu thức chính quy, như trong câu trả lời của @ Gumbo .

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

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


-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

hoặc là

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.