2013-10-03 13 views
7

perlvar alıntı:

... $/ değeri bir dize değil, bir düzenli ifade olduğunu. awk bir şey için daha iyi olmalı. :-)

Böyle bir özelliğin yararlı olabileceği durumları düşünmek zor değil - değişken uzunluklu kayıtlarla dosyaları ayrıştırma, birçok kez karşılaştığım klasik kullanım durumudur.

Şimdiye kadar sorun belleğe dosyanın tamamını yükleyerek vardı ve bunu hiç bir:

my @records = split /my_regex/, <> ; 

ancak bu teknik kullanılabilir bellek yetersiz olduğu durumlarda kullanılamaz bilinen nedenlerle

. Aslında, bir çok kez tüm kayıtların aynı anda depolanmasına gerek yoktur.

Beni $/ numaralı telefona geri getiriyor.

Dilin $/ için normal ifadeyi sağlamadığı konusunda garip buluyorum. Bu tasarım tarafından mı yapıldı? Uygulaması imkansız mı? Şık bir özellik ne olursa olsun en iyi uygulamalar olarak düşünülebilecek başka hangi geçici çözümler var?

+1

['Acme :: InputRecordSeparatorIsRegexp'] (https://metacpan.org/pod/Acme::InputRecordSeparatorIsRegexp) – mob

+1

@mob: Artık awk'le gitmesine izin veremezdin, değil mi? :) – Zaid

cevap

8

Denemeye bile gerek yok. Çoğu zaman, sonunu okumadan çizginin sonuna ulaşıp ulaşmadığınızı anlayamazsınız. Etkileşimli durumlarda bu çok kötü olabilir.

local $/ = qr/\n|\r\n?/; # Handle Windows, Unix and old MacOS line endings. 
while (1) { 
    print "Please enter a command: "; 
    my $cmd = <>; 
    $cmd =~ s{$/\z}{}; 
    process($cmd); 
} 

doğru, oldukça basit görünüyor: Örneğin

, en aşağıdaki program var diyelim? Aslında, qr/\n|\r\n?/'u desteklemek muhtemelen bu isteğin bir numaralı sebebidir. Eh, bu basit kod bile çok hatalı. ı MacOS satır sonları (CR,^M \ r) ben o (CR,^M \ r) ya da biten bir MacOS hattını verdi olmadığını o söyleyemem çünkü

$ processor 
Please enter a command: foo^M 
[hangs] 

programı kapatır kullanmak diyelim başka bir karakter yazılana kadar biten bir Windows satırı (CRLF,^M^J, \ r \ n).

İkinci, vb. Işlemek için ilk, üçüncü bir komutu işlemek için ikinci bir komut girmeliyim. Sadece bir anlam ifade etmiyor.

0

Perl6::Slurp olası workaraound benziyor:

Sen ({irs => $ your_irs_here}) için giriş işlemi giriş kayıt ayırıcı ayarlayabilirsiniz. Ayırıcı bir dize veya düzenli olarak belirtilebilir. Görebildiğim en büyük sorunlardan

+1

Dokümanlardan: "Açık bir giriş kayıt ayırıcısının skaler bir bağlamda giriş sonlandırma efekti olmadığını unutmayın, slurp her zaman" irs "değeri" – Zaid

+0

... ne olursa olsun tüm giriş akışında okur. tüm dosyayı belleğe yükleme, sonra – Zaid

4

Bir genel bir regex rekor ayırıcı destekleyen dosyanın tüm içeriği taranacak gerektirir. Örneğin, herhangi bir nedenden dolayı, /\n[^X]+\z/ numaralı bir ayırıcıyı belirtmişseniz, varsayalım. Her yeni satırdan sonra X karakterinin olup olmadığını kontrol etmek için tüm dosyanın okunması gerekir.

Yani aklınıza gelebilecek üç seçenek vardır: sadece bir "Disk belleği" ipe düzenli ifadeleri uygulanması

  • rekor ayırıcılar taramak için tüm dosyayı Tamponlama

    • dosya böylece kayıt ayırıcı olarak kullanım için standart normal ifadelerin bir alt kümesini uygulamak parça

    • okunabilir

    Bunların hiçbiri uygulama açısından çok çekici bir beklenti değildir ve mümkün olduğunda özellikle ilk seçenek Perl kodlayıcısına split kullanımı yoluyla ulaşabileceğinden bunu yapamayacağımı görebiliyorum.

  • +1

    'u ayırma İnsanların mantıklı olmayan regeeksler sağlayabilmeleri, regeksleri desteklememenin bir nedeni değildir. – ikegami

    +0

    Re "Tüm dosya sadece kayıt ayırıcıları taramak için arabelleğe alınıyor", Bu zaten bir durumdur ('$ /' ile yerel $/'' ve '$ /' içermeyen bir dosya ile) – ikegami

    3

    Perl regex motorunun (geri izleme) uygulaması, temel olarak hat sonu kullanımıyla uyumsuzdur.Bu sorunun bir kısmı, bir sonraki karakter okunduğunda tüm regex'i yeniden çalıştırmak istememenizdir. Örneğin, normal ifade

    $/ = qr/ A \w*? B | XY/; 
    

    Ve veri akışını Yani

    f o o A 1 2 X Y B b a r 
    

    alırken readline dönüş gerekir? Biz artan eşleştirme yaparsanız her pozisyonda tam regex yeniden çalıştırılırsa, biz, biz bu hale (öncelik) ile ardaşımı Bir başka deyişle,

    f o o A 1 2 X Y B b a r 
    
         A *FAIL 
         *FAIL 
    
         A\w *FAIL 
         *FAIL 
    
         A\w\w *FAIL 
         *FAIL 
    
         A\w\w\w *FAIL 
          X *FAIL 
    
         A\w\w\w\w *FAIL 
          X Y 
    
    #=> fooA12XY 
    

    olsun

    f o o A 1 2 X Y B b a r 
         A\w\w\w\w B 
    
    #=> fooA12XYB 
    

    gibi bir şey elde edebilirsiniz eşleme karmaşık. Regex motoru geri adım atmıyorsa (ancak bir tablo ayrıştırıcısı veya durum makinesi olarak çalışmayı tercih ediyorsa), tüm normal ifadeyi yeniden işlemek veya artımlı eşleme yapmak arasında hiçbir fark olmaz. Bununla birlikte, bunun mümkün olduğu regex motorları Perl regeekslerinden daha az anlamlıdır. .* istediği için

    başka sorun ((regex bir karakterden sonra zaten memnun olduğu için) hemen yanında karakteri döndürmek böyle bir “çizgi” okuma Should

    $/ = qr/ .+ /xs; 
    

    biten çizgi veya tüm dosya olurdu Mümkün olduğunca çok)? Veya şu anda içerdiği ne olursa olsun, dahili tamponun geri kalanı iade edilmeli mi?

    Satır sonları için normal ifadeleri kullanmak için, bu belirsizlikler dikkate alınmalı ve ek sınırlamalar getirilmelidir (ör. Yalnızca normal diller izin verilir).

    +0

    Görüyorum. Bu aynı zamanda awk'un bunu yapabilmesinin ve Perl'in yapamayacağı sorusunu da yanıtlıyor. – Zaid

    +0

    Verimsiz ifadeler kullanabilmeniz gerçeği, onları desteklememek için çok ikna edici bir sebep değildir. – ikegami

    +0

    $/= qr /. +/Xs; 'ile ilgili bir sorun yok (bunun yapmak için aptalca olması dışında). Düzenli olarak bile okumaya devam etmelisiniz. Örneğin. $/= "\ R \ n"; veya "$/= $ mime_sep;" şeklinde düşünün. – ikegami

    İlgili konular