2011-02-09 24 views
12

Một kịch bản thử nghiệm đơn giản:Regex trong javascript thất bại mỗi khi khác với đầu vào giống hệt

<script type="text/javascript"> 
    var reg = new RegExp('#([a-f0-9]{3})$', 'gi'); 
    for (var i = 0; i < 10; i++) { 
     console.log(reg.exec('#fff')); 
    } 
</script> 

điều khiển đầu ra:

["#fff", "fff"] 
null 
["#fff", "fff"] 
null 
["#fff", "fff"] 
null 
["#fff", "fff"] 
null 
["#fff", "fff"] 
null 

Tại sao mọi kết quả rỗng khác khi đầu vào vẫn không đổi?

+0

$ neo mẫu ở cuối dòng. Không có điều đó, một thứ như '#fff blah blah blah' cũng sẽ khớp. Tất nhiên, tại thời điểm này, regex sẽ khớp với 'blah blah blah # fff', vì nó không được neo vào đầu dòng với'^' –

Trả lời

29

Khi bạn sử dụng cờ toàn cầu, regex trở thành "dính". Tức là, nó sử dụng biến số lượt truy cập để theo dõi trong đó kết quả cuối cùng được tìm thấy. Thay vì kết hợp từ đầu mỗi lần, một regex dính sẽ thực sự nhận nơi trận đấu cuối cùng kết thúc. Bộ đếm này sẽ chỉ đặt lại về 0 (đầu) nếu toàn bộ kết quả không thành công (đó là lý do tại sao nó hoạt động mọi lúc)

Trong trường hợp của bạn, đề xuất của tôi là thả cờ g.

Để biết thêm thông tin: RegExp @ MDC

+1

Tôi không biết rằng ... bạn sống và học: D –

3

Vấn đề của bạn là "gi" trong đối số thứ hai, tôi chỉ cần loại bỏ nó và thử nghiệm trên Chrome console:

var reg = new RegExp('#([a-f0-9]{3})$'); 
9

Matt đã trả lời tại sao. Tôi chỉ muốn nói thêm rằng bạn có thể thấy điều này bằng cách kiểm tra giá trị của lastIndex trên đối tượng RegExp trước và sau khi exec gọi

var reg = new RegExp('#([a-f0-9]{3})$', 'gi'); 
for (var i = 0; i < 10; i++) { 
    console.log(reg.lastIndex); 
    console.log(reg.exec('#fff')); 
    console.log(reg.lastIndex); 
} 

ra là

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

0 
["#fff", "fff"] 
4 

4 
null 
0 

undefined 

chứng minh rằng trên mỗi iteration khác của vòng lặp, kết hợp regex bắt đầu từ nơi hoàn thành lastIndex. Bạn có thể đặt lastIndex thành 0 trước mỗi lần exec gọi hoặc bỏ cờ hoàn toàn.

1

Tôi thấy điều này trên web ...

Gọi chức năng exec() cũng làm thay đổi lastIndex tài sản của đối tượngRegExp.
Nó lưu trữ chỉ mục trong chuỗi chủ đề mà tại đó nỗ lực đối sánh tiếp theo sẽ bắt đầu.
Bạn có thể sửa đổi giá trị này để thay đổi vị trí bắt đầu của cuộc gọi tiếp theo tới exec().

Các hành vi bạn mô tả cho thấy rằng đối tượng RegExp có một trạng thái mà được điều chỉnh bằng cách gọi phương thức exec().

Tôi nghĩ bạn cần sửa đổi thuộc tính lastindex trước khi bạn chạy lại phương thức exec.
đọc thêm tại đây: Javascript Regexp Object

Các vấn đề liên quan