2010-08-10 15 views
15

से निपटने के लिए कैसे मैं वर्तमान में नियमित अभिव्यक्तियों का उपयोग करने के तरीके सीखने की कोशिश कर रहा हूं, इसलिए कृपया मेरे सरल प्रश्न के साथ सहन करें।जावा में रेगेक्स: न्यूलाइन

www.foo.com/Archives/monkeys.htm
बंदर की वेबसाइट का विवरण: उदाहरण के लिए, मैं एक इनपुट एक नई पंक्ति से अलग कर दिया लिंक का एक समूह युक्त फ़ाइल है कहते हैं।

www.foo.com/Archives/pigs.txt
सुअर की वेबसाइट का विवरण।

www.foo.com/Archives/kitty.txt
किट्टी की वेबसाइट का विवरण।

www.foo.com/Archives/apple.htm
ऐप्पल की वेबसाइट का विवरण। .*www.*\\s.*Pig.*

हालांकि, जब मैं अपने कोड के भीतर इसे चलाने की कोशिश यह काम करने के लिए प्रतीत नहीं होता:

अगर मैं अपने विवरण के साथ एक वेबसाइट प्राप्त करना चाहता था, इस regex एक परीक्षण उपकरण पर काम करने लगता है । क्या यह अभिव्यक्ति सही है? मैंने "\ s" को "\ n" के साथ बदलने की कोशिश की और यह अभी भी काम नहीं कर रहा है।

उत्तर

0

वर्क्स मेरे लिए:

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

शायद समस्या जिस तरह से आप पैटर्न और Matcher वस्तुओं उपयोग कर रहे थे के साथ था?

+1

यह केवल तभी काम करता है जब रेखाएं हमेशा \ n के साथ स्वरूपित हों, जैसे यूनिक्स – Gary

32

लाइनें शायद आपकी फ़ाइल में \r\n से अलग हो गई हैं। \r (कैरिज रिटर्न) और \n (लाइनफीड) को जावा रेगेक्स में लाइन-सेपरेटर वर्ण माना जाता है, और . मेटाएक्टेक्टर उनमें से किसी से मेल नहीं खाएगा। \s उन पात्रों से मेल खाएगा, इसलिए यह \r का उपभोग करता है, लेकिन .*\n से मेल खाने के लिए छोड़ देता है, जो विफल रहता है। आपके परीक्षक ने लाइनों को अलग करने के लिए शायद \n का उपयोग किया था, जिसे \s द्वारा खपत किया गया था।

यदि मैं सही हूं, तो \s से \s+ या [\r\n]+ को बदलना चाहिए, इसे काम करना चाहिए। शायद इस मामले में आपको बस इतना करना है, लेकिन कभी-कभी आपको बिल्कुल एक लाइन विभाजक से मेल खाना पड़ेगा, या कम से कम आप कितने मेल खाते हैं इसका ट्रैक रखें। उस स्थिति में आपको एक रेगेक्स की आवश्यकता होती है जो तीन सबसे आम लाइन विभाजक प्रकारों में से किसी एक में से मेल खाती है: \r\n (विंडोज़/डॉस), \n (यूनिक्स/लिनस/ओएसएक्स) और \r (पुराने मैक)। इनमें से किसी भी करेंगे:

\r\n|[\r\n] 

\r\n|\n|\r 

अद्यतन: जावा 8 के रूप में हम एक और विकल्प है, \R। यह किसी भी लाइन विभाजक से मेल खाता है, जिसमें केवल \r\n शामिल नहीं है, लेकिन Unicode standard द्वारा परिभाषित कई अन्य।यह इस के बराबर है:

\r\n|[\n\x0B\x0C\r\u0085\u2028\u2029] 

यहाँ कैसे आप इसका इस्तेमाल दे सकता है:

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

i विकल्प यह केस-संवेदी बनाता है, और m बहु मोड में कहते हैं, मैच के लिए ^ और $ की इजाजत दी लाइन सीमाओं पर।

0

इस संस्करण में नई-पंक्तियों कि हो सकता है या तो विंडोज (\ r \ n) या यूनिक्स (\ N)

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

भविष्य में संदर्भ के लिए मेल खाता है की कोशिश, एक भी उपयोग कर सकते हैं "।" के लिए पैटर्न। डॉटल ध्वज \ r या \ n से मिलान करने के लिए।

उदाहरण:

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

हम इस तरह HTTP हेडर लाइनों (प्रत्येक पंक्ति के साथ \ r \ n समाप्त हो गया)

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 

यह पैटर्न की एक एकल स्ट्रिंग को पार्स कर रहे हैं कहो

"matcher.group (1)" का उपयोग कर स्थान मान को पार्स कर सकते हैं।

"।" उपर्युक्त पैटर्न में \ r और \ n मिलान होगा, इसलिए उपर्युक्त पैटर्न वास्तव में http शीर्षलेख रेखाओं से 'स्थान' को पार्स कर सकता है, जहां लक्ष्य रेखा से पहले या बाद में अन्य शीर्षलेख हो सकते हैं (यह नहीं कि यह एक अनुशंसित तरीका है पार्स http शीर्षलेख)।

इसके अलावा, आप उसी प्रभाव को प्राप्त करने के लिए पैटर्न के अंदर "?" का उपयोग कर सकते हैं।

यदि आप ऐसा कर रहे हैं, तो आप Matcher.find() का उपयोग करके बेहतर हो सकते हैं।

+0

डॉटल इस मामले में वास्तव में उपयोगी नहीं है। ओपी को यह जानने की जरूरत है कि रेगेक्स लाइन विभाजक का उपभोग करता है ताकि वह सुनिश्चित हो सके कि वह उनमें से केवल एक से मेल खाता है। और यह आपके उदाहरण में भी कम उपयोगी है, जहां ब्याज की सभी सामग्री एक पंक्ति में निहित है। मैं शायद ही कभी डॉटल मोड का उपयोग करता हूं; ऐसा लगता है कि यह हल होने से अधिक समस्याएं पैदा करता है। –

+0

आप शायद सही हैं, लेकिन यह मेरे उदाहरण में उपयोगी है, हालांकि, मेरे एकल स्ट्रिंग को वास्तव में सभी पंक्तियां थीं। – javaPhobic

+0

डॉटल मोड के बारे में बात यह है कि यह बहुत ही शरारत के दायरे को फैलाता है। उदाहरण के लिए, जब मैं आपके नमूना डेटा में अपना रेगेक्स लागू करता हूं, तो पहले '। *?' 'हेडर' हेडर के ऊपर सूचीबद्ध सभी शीर्षकों का उपभोग करता है। मुझे पता है कि आप केवल उस यूआरएल की परवाह करते हैं जिसे आप समूह # 1 में कैप्चर कर रहे हैं, लेकिन आप इसे अभी भी डॉटल मोड से प्राप्त करेंगे, और आप रेगेक्स के लिए बहुत अनावश्यक काम बचाएंगे। –

संबंधित मुद्दे