Đếm số trận đấu của một regex trong Javascript


98

Tôi muốn viết một regex để đếm số lượng khoảng trắng / tab / dòng mới trong một đoạn văn bản. Vì vậy, tôi ngây thơ viết như sau: -

numSpaces : function(text) { 
    return text.match(/\s/).length; 
}

Vì một số lý do không xác định, nó luôn trả về 1. Vấn đề với câu lệnh trên là gì? Kể từ đó tôi đã giải quyết được vấn đề với những điều sau: -

numSpaces : function(text) { 
    return (text.split(/\s/).length -1); 
}

Câu trả lời:


191

tl; dr: Bộ đếm Mẫu Chung

// THIS IS WHAT YOU NEED
const count = (str) => {
  const re = /YOUR_PATTERN_HERE/g
  return ((str || '').match(re) || []).length
}

Đối với những người đến đây đang tìm kiếm một cách chung để đếm số lần xuất hiện của mẫu regex trong một chuỗi và không muốn nó bị lỗi nếu không có lần xuất hiện nào, thì mã này là thứ bạn cần. Đây là một minh chứng:

/*
 *  Example
 */

const count = (str) => {
  const re = /[a-z]{3}/g
  return ((str || '').match(re) || []).length
}

const str1 = 'abc, def, ghi'
const str2 = 'ABC, DEF, GHI'

console.log(`'${str1}' has ${count(str1)} occurrences of pattern '/[a-z]{3}/g'`)
console.log(`'${str2}' has ${count(str2)} occurrences of pattern '/[a-z]{3}/g'`)

Câu trả lời gốc

Vấn đề với mã ban đầu của bạn là bạn đang thiếu số nhận dạng chung :

>>> 'hi there how are you'.match(/\s/g).length;
4

Nếu không có gphần của regex, nó sẽ chỉ khớp với lần xuất hiện đầu tiên và dừng lại ở đó.

Cũng lưu ý rằng regex của bạn sẽ đếm các khoảng trắng liên tiếp hai lần:

>>> 'hi  there'.match(/\s/g).length;
2

Nếu điều đó không mong muốn, bạn có thể làm điều này:

>>> 'hi  there'.match(/\s+/g).length;
1

5
Điều này hoạt động miễn là bạn có ít nhất một khoảng trống trong đầu vào của mình. Nếu không, match () trả về null một cách khó chịu.
sfink

3
sfink là đúng, bạn chắc chắn muốn kiểm tra xem trận đấu () trở null:var result = text.match(/\s/g); return result ? result.length : 0;
Gras đúp

37
Bạn cũng có thể bảo vệ khỏi null bằng cách sử dụng cấu trúc này:( str.match(...) || [] ).length
a'r

11

Như đã đề cập trong câu trả lời trước đó của tôi , bạn có thể sử dụng RegExp.exec()để lặp lại tất cả các trận đấu và đếm từng lần xuất hiện; lợi thế là chỉ giới hạn ở bộ nhớ, vì nói chung, nó chậm hơn khoảng 20% ​​so với việc sử dụng String.match().

var re = /\s/g,
count = 0;

while (re.exec(text) !== null) {
    ++count;
}

return count;


2

('my string'.match(/\s/g) || []).length;


1
Tôi nghĩ rằng bạn đặt || []ở vị trí sai, nó phải là('my string'.match(/\s/g) || []).length
woojoo666

0

Đây chắc chắn là một thứ có rất nhiều cạm bẫy. Tôi đã làm việc với câu trả lời của Paolo Bergantino và nhận ra rằng ngay cả câu trả lời đó cũng có một số hạn chế. Tôi thấy làm việc với các biểu diễn chuỗi ngày là một nơi tốt để nhanh chóng tìm ra một số vấn đề chính. Bắt đầu với một chuỗi đầu vào như sau: '12-2-2019 5:1:48.670'

và thiết lập chức năng của Paolo như sau:

function count(re, str) {
    if (typeof re !== "string") {
        return 0;
    }
    re = (re === '.') ? ('\\' + re) : re;
    var cre = new RegExp(re, 'g');
    return ((str || '').match(cre) || []).length;
}

Tôi muốn biểu thức chính quy được truyền vào, để hàm có thể sử dụng lại nhiều hơn, thứ hai, tôi muốn tham số là một chuỗi, để khách hàng không phải tạo regex, mà chỉ cần khớp trên chuỗi, như một phương thức lớp tiện ích chuỗi tiêu chuẩn.

Bây giờ, ở đây bạn có thể thấy rằng tôi đang giải quyết các vấn đề với đầu vào. Với những điều sau đây:

if (typeof re !== "string") {
    return 0;
}

Tôi đảm bảo rằng các đầu vào không phải là bất cứ điều gì giống như đen 0, false, undefined, hay null, không ai trong số đó là chuỗi. Vì những ký tự này không có trong chuỗi đầu vào, nên không có kết quả phù hợp, nhưng nó phải khớp '0', đó là một chuỗi.

Với những điều sau đây:

re = (re === '.') ? ('\\' + re) : re;

Tôi đang giải quyết thực tế là hàm tạo RegExp sẽ (tôi nghĩ là sai) diễn giải chuỗi '.'là trình khớp tất cả các ký tự\.\

Cuối cùng, vì tôi đang sử dụng hàm tạo RegExp, tôi cần đặt 'g'cờ toàn cục cho nó để nó đếm tất cả các kết quả phù hợp, không chỉ kết quả đầu tiên, tương tự như các đề xuất trong các bài viết khác.

Tôi nhận ra rằng đây là một câu trả lời cực kỳ muộn, nhưng nó có thể hữu ích cho ai đó đang vấp phải ở đây. BTW đây là phiên bản TypeScript:

function count(re: string, str: string): number {
    if (typeof re !== 'string') {
        return 0;
    }
    re = (re === '.') ? ('\\' + re) : re;
    const cre = new RegExp(re, 'g');    
    return ((str || '').match(cre) || []).length;
}

-2

như thế này thì sao

function isint(str){
    if(str.match(/\d/g).length==str.length){
        return true;
    }
    else {
         return false
    }
}
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.