2010-08-10 16 views
15

ile nasıl başa çıkmalıyım Şu anda normal ifadeleri nasıl kullanacağımı öğrenmeye çalışıyorum, bu yüzden lütfen basit soruma bakın.Java'da RegEx:

www.foo.com/Archives/monkeys.htm Maymun web sitesinin
Açıklaması: Örneğin, ben bir satır ile ayrılmış bağlantıları bir demet içeren bir giriş dosyası olduğunu varsayalım.

www.foo.com/Archives/pigs.txt
Pig'un web sitesinin açıklaması.

www.foo.com/Archives/kitty.txt
Kitty'nin web sitesinin açıklaması.

www.foo.com/Archives/apple.htm
Apple'ın web sitesinin açıklaması. Ancak .*www.*\\s.*Pig.*

, benim kodunda bunun çalıştıran olan çalışmıyor görünmüyor: Ben onun açıklama ile birlikte bir web sitesi almak istiyorsa

, bu regex bir test aracı üzerinde çalışmak gibi görünüyor . Bu ifade doğru mu? "\ S" yi "\ n" ile değiştirmeyi denedim ve hala çalışmıyor gibi görünüyor. Benim için

cevap

0

Çalışır:

import java.util.regex.Pattern; 
import java.util.regex.Matcher; 
public class Foo { 
    public static void main(String args[]) { 
    Pattern p = Pattern.compile(".*www.*\\s.*Pig.*"); 
    String s = "www.foo.com/Archives/monkeys.htm\n" 
      + "Description of Monkey's website.\n" 
      + "\n" 
      + "www.foo.com/Archives/pigs.txt\n" 
      + "Description of Pig's website.\n" 
      + "\n" 
      + "www.foo.com/Archives/kitty.txt\n" 
      + "Description of Kitty's website.\n" 
      + "\n" 
      + "www.foo.com/Archives/apple.htm\n" 
      + "Description of Apple's website.\n"; 
    Matcher m = p.matcher(s); 
    if (m.find()) { 
     System.out.println(m.group()); 
    } else { 
     System.out.println("ERR: no match"); 
    } 
    } 
} 

Belki sorun Desen ve eşleştirici nesneleri kullanarak şeklinden oldu?

+1

Bu yalnızca satırların her zaman \ n ile biçimlendirilmiş olması durumunda çalışır; – Gary

32

Çizgiler, dosyanıza muhtemelen \r\n ile ayrılmıştır. Hem \r (satır başı) hem de(satır besleme), Java düzenli ifadelerinde satır ayırıcı karakterler olarak kabul edilir ve . meta karakter, bunlardan hiçbiriyle eşleşmez. \s, bu karakterlerle eşleşecek, bu nedenle \r'u tüketir, ancak 'u \n ile eşleşir ve bu da başarısız olur. Test cihazınız muhtemelen \s tarafından tüketilen hatları ayırmak için sadece \n'u kullandı.

Eğer haklıysam, \s değerini \s+ veya [\r\n]+ değiştirerek çalışmasını sağlamalı. Muhtemelen bu durumda yapmanız gereken tek şey budur, ancak bazen tam olarak bir satır ayırıcıyla eşleşmeli veya en azından kaç tane eşleştiğini takip etmelisiniz. Bu durumda, en yaygın üç satır ayırıcı türünden biriyle eşleşen bir normal ifadeye gereksiniminiz vardır: \r\n (Windows/DOS), \n (Unix/Linus/OSX) ve \r (eski Mac'ler). Bunların Ya yapacağız:

\r\n|[\r\n] 

\r\n|\n|\r 

Güncelleme: Java 8 itibariyle biz \R başka bir seçenek vardır. Sadece \r\n değil, Unicode standard tarafından tanımlandığı gibi herhangi bir satır ayırıcıyla eşleşir.

İşte
\r\n|[\n\x0B\x0C\r\u0085\u2028\u2029] 

sen nasıl kullanılabileceğine var: Bu eşdeğerdir

(?im)^.*www.*\R.*Pig.*$ 

i seçeneği harf duyarsız hale getirir ve m maç için ^ ve $ izin satırlı modda koyar sınırlarda.

0

Bu sürüm ya Pencereler (\ r \ n) veya Unix (\ n) İleride

Pattern p = Pattern.compile("(www.*)((\r\n)|(\n))(.*Pig.*)"); 
String s = "www.foo.com/Archives/monkeys.htm\n" 
      + "Description of Monkey's website.\n" 
      + "\r\n" 
      + "www.foo.com/Archives/pigs.txt\r\n" 
      + "Description of Pig's website.\n" 
      + "\n" 
      + "www.foo.com/Archives/kitty.txt\n" 
      + "Description of Kitty's website.\n" 
      + "\n" 
      + "www.foo.com/Archives/apple.htm\n" 
      + "Description of Apple's website.\n"; 
Matcher m = p.matcher(s); 
if (m.find()) { 
    System.out.println("found: "+m.group()); 
    System.out.println("website: "+m.group(1)); 
    System.out.println("description: "+m.group(5)); 
} 
System.out.println("done"); 
9

olabilir yeni satır maçları deneyin, bir de kullanabilirsiniz "." Için Pattern.DOTALL bayrağı. eşittir \ r veya \ n.

Örnek:

final static Pattern PATTERN_LOCATION = Pattern.compile(".*?Location\\: (.*?)\\r.*?", Pattern.DOTALL); 
:

böyle http başlık hatları (her satır \ r \ n ile sona)

HTTP/1.1 302 Found 
Server: Apache-Coyote/1.1 
Cache-Control: no-cache, no-store, max-age=0, must-revalidate 
Pragma: no-cache 
Expires: 0 
X-Frame-Options: SAMEORIGIN 
Location: http://localhost:8080/blah.htm 
Content-Length: 0 

Bu model, tek bir dizi ayrıştırma ki

"matcher.group (1)" kullanarak konum değerini ayrıştırabilir.

"." Yukarıdaki modelde, \ r ve \ n eşleşecektir, dolayısıyla yukarıdaki şablon, hedef satırından önce veya sonra diğer başlıkların olabileceği http başlık satırlarından 'Konum'u ayrıştırabilir. http başlıklarını ayrıştır).

Ayrıca, aynı efekti elde etmek için desen içinde "? S" kullanabilirsiniz.

Bunu yapıyorsanız, Matcher.find() öğesini kullanarak daha iyi olabilirsiniz.

+0

unix gibi DOTALL bu durumda gerçekten yararlı değildir. OP'in satırsal ayırıcıyı ne zaman harcadığını bilmesi gerekir, böylece yalnızca bunlardan birini eşleştirdiğinden emin olabilir. Ve örneğinizde, ilgilendiğiniz içeriğin bir satırda yer aldığı daha az yararlıdır. DOTALL modunu neredeyse hiç kullanmıyorum; çözdüğünden daha fazla sorun yaratıyor gibi görünüyor. –

+0

Muhtemelen haklısınız, ama benim örneğimde yararlı olsa da, benim ayrıştırmak için benim tek string aslında tüm satırları vardı. – javaPhobic

+0

DOTALL moduyla ilgili olan şey, felaketin kapsamını muazzam ölçüde genişletmesidir. Örneğin, regex'inizi örnek verilerinize uyguladığımda, ilk '. *?', 'Location' başlığının üstünde listelenen tüm başlıkları kullanır. Sadece 1. grupta yakaladığınız URL'yi önemsediğinizi biliyorum, ancak yine de DOTALL modunu kullanmaya devam edersiniz ve normal ifadeler için gereksiz yere çok fazla iş çıkarırsınız. –