Cờ đa cấp regex JavaScript không hoạt động


265

Tôi đã viết một biểu thức chính quy để tìm nạp chuỗi từ HTML, nhưng có vẻ như cờ đa dòng không hoạt động.

Đây là mẫu của tôi và tôi muốn lấy văn bản trong h1thẻ.

var pattern= /<div class="box-content-5">.*<h1>([^<]+?)<\/h1>/mi
m = html.search(pattern);
return m[1];

Tôi đã tạo một chuỗi để kiểm tra nó. Khi chuỗi chứa "\ n", kết quả luôn là null. Nếu tôi xóa tất cả "\ n", nó sẽ cho tôi kết quả đúng, bất kể có hay không có /mcờ.

Có gì sai với regex của tôi?


14
Không sử dụng các biểu thức thông thường để phân tích HTML, HTML KHÔNG phải là ngôn ngữ thông thường. Sử dụng một trình phân tích cú pháp HTML, resp. DOM. Điều đó cũng đơn giản hơn nhiều.
Svante

Bạn đang tìm kiếm DOTALL, không phải multiline.
Vanuan

Lưu ý rằng JavaScript sẽ sớm có công cụ dotAllsửa đổi để bạn có thể làm /.../svà các dấu chấm của bạn cũng sẽ khớp với các dòng mới. Kể từ tháng 7 năm 2017, nó đứng sau một lá cờ trong Chrome.

Câu trả lời:


609

Bạn đang tìm kiếm công cụ /.../ssửa đổi, còn được gọi là công cụ sửa đổi dotall . Nó buộc dấu chấm .cũng khớp với các dòng mới, điều mà nó không làm theo mặc định.

Tin xấu là nó không tồn tại trong JavaScript (nó không có trong ES2018, xem bên dưới) . Tin tốt là bạn có thể làm việc xung quanh nó bằng cách sử dụng một lớp nhân vật (ví dụ \s) và phủ định của nó ( \S) với nhau, như thế này:

[\s\S]

Vì vậy, trong trường hợp của bạn, regex sẽ trở thành:

/<div class="box-content-5">[\s\S]*<h1>([^<]+?)<\/h1>/i

Kể từ ES2018, JavaScript hỗ trợ scờ (dot ALL), do đó, trong môi trường hiện đại, biểu thức chính quy của bạn có thể giống như bạn đã viết, nhưng với một scờ ở cuối (thay vì m; mthay đổi cách thức ^$hoạt động, không phải .):

/<div class="box-content-5">.*<h1>([^<]+?)<\/h1>/is

5
@simo Phù hợp với bất kỳ ký tự khoảng trắng hoặc không khoảng trắng, phù hợp hiệu quả với bất kỳ ký tự nào. Nó giống như ., nhưng phù hợp với khoảng trắng quá ( \s) có nghĩa là nó khớp \n(điều .này không làm trong JavaScript hoặc có thể được thực hiện với scờ).
alex

1
Câu trả lời này đã được thêm vào Câu hỏi thường gặp về Biểu thức thường xuyên chồng chéo , trong phần "Công cụ sửa đổi".
aliteralmind

40
Theo MDN, [^]cũng hoạt động để phù hợp với bất kỳ ký tự nào, bao gồm cả dòng mới, trong JavaScript. Xem developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/iêu
Dan Allen

6
Đối với các vấn đề về hiệu suất, rất nên sử dụng bộ *?định lượng thay vì *để tránh sự tham lam. Điều này sẽ tránh bắt <h1> cuối cùng của tài liệu: đó có thể không phải là điều bạn muốn và không hiệu quả vì regrec sẽ tiếp tục tìm kiếm <h1> cho đến khi kết thúc chuỗi ngay cả khi nó đã tìm thấy trước đó.
KrisWebDev

9
Phiên bản [^] dễ dàng hơn trên trình biên dịch regrec và cũng ngắn gọn hơn.
Erik Corry

21

Bạn muốn công scụ sửa đổi (dotall), dường như không tồn tại trong Javascript - bạn có thể thay thế .bằng [\ s \ S] theo đề xuất của @molf. Công cụ msửa đổi (multiline) tạo ra các dòng khớp ^ và $ thay vì toàn bộ chuỗi.


4
Bạn có thể thêm rằng công cụ sửa đổi / s "đặt chế độ đơn tuyến trái ngược với chế độ đa dòng. +1
Cerebrus

Chín năm sau, JavaScript hiện có scờ (ES2018). :-)
TJ Crowder

12

[\s\S]đã không làm việc cho tôi trong nodejs 6.11.3. Dựa trên tài liệu RegExp , nó nói sử dụng [^]cái nào phù hợp với tôi.

(Dấu chấm, dấu thập phân) khớp với bất kỳ ký tự đơn nào ngoại trừ dấu kết thúc dòng: \ n, \ r, \ u2028 hoặc \ u2029.

Bên trong một bộ ký tự, dấu chấm mất đi ý nghĩa đặc biệt của nó và khớp với một dấu chấm theo nghĩa đen.

Lưu ý rằng cờ m multiline không thay đổi hành vi dấu chấm. Vì vậy, để khớp một mẫu trên nhiều dòng, bộ ký tự [^] có thể được sử dụng (tất nhiên nếu bạn không có nghĩa là một phiên bản IE cũ), thì nó sẽ khớp với bất kỳ ký tự nào kể cả dòng mới.

Ví dụ:

/This is on line 1[^]*?This is on line 3/m

* ở đâu? là sự tham lam không tham lam của 0 hoặc nhiều lần xuất hiện của [^].


1
Đối với những người thắc mắc điều đó [^]có nghĩa là gì : nó giống như một phủ định kép: "khớp với bất kỳ ký tự nào không có trong danh sách trống này " và do đó, nói đến "khớp với bất kỳ ký tự nào" .
trincot

8

Công cụ sửa đổi dotall đã thực sự biến nó thành JavaScript vào tháng 6 năm 2018, đó là ECMAScript 2018.
https://github.com/tc39/proposed-regapi-dotall-flag

const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`.
re.test('foo\nbar');
// → true
re.dotAll
// → true
re.flags
// → 's'

0

Đề nghị của tôi là tốt hơn hết là chia chuỗi nhiều dòng bằng "\ n" và nối các phần tách của chuỗi gốc và trở thành một dòng đơn và dễ thao tác.

<textarea class="form-control" name="Body" rows="12" data-rule="required" 
                  title='@("Your feedback ".Label())'
                  placeholder='@("Your Feedback here!".Label())' data-val-required='@("Feedback is required".Label())'
                  pattern="^[0-9a-zA-Z ,;/?.\s_-]{3,600}$" data-val="true" required></textarea>


$( document ).ready( function() {
  var errorMessage = "Please match the requested format.";
  var firstVisit = false;

  $( this ).find( "textarea" ).on( "input change propertychange", function() {

    var pattern = $(this).attr( "pattern" );
    var element = $( this );

    if(typeof pattern !== typeof undefined && pattern !== false)
    {
      var ptr = pattern.replace(/^\^|\$$/g, '');
      var patternRegex = new RegExp('^' + pattern.replace(/^\^|\$$/g, '') + '$', 'gm');     

      var ks = "";
      $.each($( this ).val().split("\n"), function( index, value ){
        console.log(index + "-" + value);
        ks += " " + value;
      });      
      //console.log(ks);

      hasError = !ks.match( patternRegex );
      //debugger;

      if ( typeof this.setCustomValidity === "function") 
      {
        this.setCustomValidity( hasError ? errorMessage : "" );
      } 
      else 
      {
        $( this ).toggleClass( "invalid", !!hasError );
        $( this ).toggleClass( "valid", !hasError );

        if ( hasError ) 
        {
          $( this ).attr( "title", errorMessage );
        } 
        else
        {
          $( this ).removeAttr( "title" );
        }
      }
    }

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