JavaScript normal ifade çok satırlı bayrağı çalışmıyor


265

HTML'den dize almak için bir regex yazdım, ancak çok satırlı bayrak çalışmıyor gibi görünüyor.

Bu benim modelim ve metni h1etikete almak istiyorum .

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

Test etmek için bir dize oluşturdum. Dize "\ n" içerdiğinde, sonuç her zaman null olur. Tüm "\ n" leri kaldırsaydım, /mbayraklı olsun olmasın bana doğru sonucu verdi .

Normal ifademin nesi var?


14
HTML'yi ayrıştırmak için normal ifadeler kullanmayın, HTML normal bir dil DEĞİLDİR. Bir HTML ayrıştırıcı kullanın, sırasıyla. DOM. Bu da çok daha basit.
Svante

Çok satırlı değil DOTALL'u arıyorsunuz.
Vanuan

Yakında JavaScript'in dotAlldeğiştiriciye sahip olacağını ve böylece /.../snoktalarınızın yeni satırlarla eşleşeceğini unutmayın. Temmuz 2017 itibariyle, Chrome'daki bir bayrağın arkasında.

Yanıtlar:


609

Dotall değiştiricisi /.../solarak da bilinen değiştiriciyi arıyorsunuz . Noktayı, varsayılan olarak yapmadığı yeni satırlarla da eşleşmeye zorlar ..

Kötü haber, JavaScript'te bulunmamasıdır (ES2018'den beri var, aşağıya bakın) . İyi haber şu ki, bir karakter sınıfını (örn. \s) Ve olumsuzluğunu ( \S) birlikte kullanarak şöyle çalışabilirsiniz :

[\s\S]

Yani sizin durumunuzda normal ifade şöyle olur:

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

ES2018 itibariyle JavaScript destekleyen syüzden yazdım gibi düzenli ifade olabilir modern bir ortamda, (dotall) bayrağı, ancak bir ile ssonunda bayrağı (ziyade m; mdeğişiklikleri nasıl ^ve $iş, değil .):

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

5
@simo Herhangi bir karakteri eşleştirerek, boşluk veya boşluk olmayan karakterlerle eşleşir. Bu gibidir ., ancak eşleşen boşluk da ( \s) eşleştiği anlamına gelir \n( .JavaScript'te yapılmaz veya sbayrakla yapılabilir).
alex

1
Bu yanıt, "Değiştiriciler" altında Yığın Taşması Düzenli İfade SSS'ye eklendi .
aliteralmind

40
MDN'ye göre [^], JavaScript'te yeni satırlar da dahil olmak üzere herhangi bir karakteri eşleştirmek için çalışıyor. Bkz. Developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Dan Allen

6
Performans sorunları için, açgözlülüğü önlemek için *?nicelik belirtecinin kullanılması önemle tavsiye edilir *. Bu , belgenin son <h1> 'ını yakalamaktan kaçınacaktır : muhtemelen istediğiniz şey bu değildir ve regexp, daha önce bulmuş olsa bile dizenin sonuna kadar <h1> aramaya devam edeceği için bu etkili değildir.
KrisWebDev

9
[^] Sürümü regexp derleyicisinde çok daha kolay ve aynı zamanda daha kısa.
Erik Corry

21

Sen istiyorsun sanlaşılan JavaScript yok (dotall) değiştirici, - sen yerine .sahip [\ s \ S] @molf tarafından önerildiği gibi. m(Multiline) değiştirici markaları ^ $ ve maç hatları tamamı yerine dize.


4
/ S "değiştiricisinin çok satırlı modun aksine tek satır modunu ayarladığını ekleyebilirsiniz. +1
Cerebrus

Dokuz yıl sonra JavaScript artık sbayrağa sahip (ES2018). :-)
TJ Crowder

12

[\s\S]benim için işe yaramadı nodejs 6.11.3. Dayanarak RegExp belgelerine , kullanmak için diyor [^]benim için çalışır hangi.

(Nokta, ondalık noktası), satır sonlandırıcılar dışında herhangi bir karakterle eşleşir: \ n, \ r, \ u2028 veya \ u2029.

Bir karakter kümesinin içinde, nokta özel anlamını kaybeder ve gerçek bir nokta ile eşleşir.

M çok satırlı bayrağın nokta davranışını değiştirmediğini unutmayın. Dolayısıyla, bir kalıbı birden çok satırda eşleştirmek için [^] karakter kümesi kullanılabilir (elbette eski bir IE sürümü anlamına gelmezse), yeni satırlar dahil herhangi bir karakterle eşleşir.

Örneğin:

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

nerede *? [^] 0 veya daha fazla tekrarlanan açgözlü kapamadır.


1
Ne [^]anlama geldiğini merak edenler için : bu bir çifte olumsuzlama gibidir: " bu boş listede olmayan herhangi bir karakteri eşleştir " ve böylece "herhangi bir karakteri eşleştir" demeye gelir .
trincot


0

Benim önerim, çok satırlı dizeyi "\ n" ile bölmenin ve orijinal dizenin bölümlerini birleştirmenin daha iyi olması ve tek bir satır haline gelmesi ve kullanımı kolay olmasıdır.

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

  });
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.