रेगेक्स में एक शब्द सीमा क्या है?


137

मैं जावा 1.6 में जावा रेगीक्स का उपयोग कर रहा हूं (अन्य उद्देश्यों के बीच संख्यात्मक आउटपुट को पार्स करने के लिए) और इसकी सटीक परिभाषा नहीं पा सकता है \b ("शब्द सीमा") । मैंने यह मान लिया था कि -12यह एक "पूर्णांक शब्द" (द्वारा मिलान \b\-?\d+\b) होगा, लेकिन ऐसा प्रतीत होता है कि यह काम नहीं करता है। मैं अंतरिक्ष-पृथक संख्याओं के मिलान के तरीकों के बारे में जानने के लिए आभारी रहूंगा।

उदाहरण:

Pattern pattern = Pattern.compile("\\s*\\b\\-?\\d+\\s*");
String plus = " 12 ";
System.out.println(""+pattern.matcher(plus).matches());
String minus = " -12 ";
System.out.println(""+pattern.matcher(minus).matches());
pattern = Pattern.compile("\\s*\\-?\\d+\\s*");
System.out.println(""+pattern.matcher(minus).matches());

यह रिटर्न:

true
false
true

क्या आप इनपुट और अपेक्षित आउटपुट के साथ एक छोटा सा उदाहरण पोस्ट कर सकते हैं?
ब्रेंट राइट्स कोड

उदाहरण पैटर्न पैटर्न = Pattern.compile ("\\ s * \\ b \\ -? \\ d + \\ s *"); स्ट्रिंग प्लस = "12"; Println ( "" + pattern.matcher (धन) .matches ()); स्ट्रिंग माइनस = "-12"; Println ( "" + pattern.matcher (ऋण) .matches ()); pattern = pattern.compile ("\\ s * \\ -? \\ d + \\ s *"); Println ( "" + pattern.matcher (ऋण) .matches ()); देता है: सच झूठ सच
peter.murray.rust

जवाबों:


97

एक शब्द सीमा, अधिकांश रेगेक्स बोलियों में, \wऔर \W(स्ट्रिंग शब्द की शुरुआत या अंत में या एक शब्द चरित्र) () के साथ शुरू होती है या समाप्त होती है (क्रमशः) के बीच की स्थिति [0-9A-Za-z_]

तो, स्ट्रिंग में "-12", यह 1 से पहले या 2 के बाद मैच होगा। डैश एक शब्द चरित्र नहीं है।


35
Correctamundo। \bएक शून्य-चौड़ाई का दावा है जो \wएक तरफ होता है, और या तो \Wदूसरे पर होता है या स्थिति स्ट्रिंग के आरंभ या अंत में होती है। \wमनमाने ढंग से "पहचानकर्ता" अक्षर (अलनम्स और अंडरस्कोर) के रूप में परिभाषित किया गया है, विशेष रूप से अंग्रेजी के लिए कुछ भी उपयोगी नहीं है।
हॉब

100% सही है। सिर्फ आपकी टिप्पणी करने के लिए माफी नहीं। आपका जवाब देखने से पहले मैंने सबमिट सबमिट कर दिया।
ब्रेंट राइट्स कोड

5
समझ के लिए, क्या \bhello\bउपयोग के बिना रीगेक्स को फिर से लिखना संभव है \b(उपयोग करते हुए \w,)\W और अन्य) के ?
डेविड पोर्टेबेला

5
इसके प्रकार: (^|\W)hello($|\W)इसके अलावा, यह पहले और बाद में किसी भी गैर-शब्द वर्ण पर कब्जा नहीं करेगा, इसलिए यह अधिक पसंद होगा (^|(?<=\W))hello($|(?=\W))(लुकहेड / लुकअप एसेसरीज का उपयोग करके)।
9

6
@ अरबपति थोड़ा सरल (?<!\w)hello(?!\w):।
डेविड नाइप

28

एक शब्द सीमा तीन स्थितियों में से एक में हो सकती है:

  1. स्ट्रिंग में पहले चरित्र से पहले, यदि पहला वर्ण एक शब्द चरित्र है।
  2. स्ट्रिंग में अंतिम वर्ण के बाद, यदि अंतिम वर्ण एक शब्द वर्ण है।
  3. तार में दो वर्णों के बीच, जहाँ एक शब्द वर्ण है और दूसरा शब्द वर्ण नहीं है।

शब्द अक्षर अल्फा-न्यूमेरिक हैं; माइनस साइन नहीं है। रेगेक्स ट्यूटोरियल से लिया गया ।


21

नियमित अभिव्यक्ति सीखने के दौरान, मैं वास्तव में मेटाचैकर में फंस गया था \b। जब मैं अपने आप से पूछ रहा था तो मैंने वास्तव में इसका अर्थ नहीं समझा था " यह क्या है, यह " दोहरावदार है। वेबसाइट का उपयोग करके कुछ प्रयासों के बाद , मैं शब्दों की हर शुरुआत में और शब्दों के अंत में गुलाबी ऊर्ध्वाधर डैश को देखता हूं। मुझे इसका मतलब उस समय अच्छी तरह से मिला। अब यह ठीक-ठीक शब्द ( \w) है

मेरा नजरिया बेहद समझ-बूझ के लिए है। इसके पीछे तर्क को दूसरे उत्तरों से जांचा जाना चाहिए।

यहाँ छवि विवरण दर्ज करें


3
यह समझने के लिए एक बहुत अच्छी साइट है कि एक शब्द सीमा क्या है और मैच कैसे हो रहे हैं
vsingh

2
यह पोस्ट बताने के बजाय दिखाने के श्रेय की हकदार है। एक चित्र की एक हजार शब्दों की कीमत है।
M_M

13

शब्द सीमा एक ऐसी स्थिति है जो या तो एक शब्द चरित्र से पहले होती है और एक के बाद एक नहीं होती है, या एक शब्द चरित्र द्वारा पीछा की जाती है और एक से पहले नहीं होती है।


8

मैं बात करता हूं कि क्या \b-स्टाइल रेगेक्स की सीमाएं वास्तव में यहां हैं

लघुकथा यह है कि वे सशर्त हैं । उनका व्यवहार इस बात पर निर्भर करता है कि वे आगे क्या कर रहे हैं।

# same as using a \b before:
(?(?=\w) (?<!\w)  | (?<!\W) )

# same as using a \b after:
(?(?<=\w) (?!\w)  | (?!\W)  )

कभी-कभी ऐसा नहीं होता है जो आप चाहते हैं। विस्तार के लिए मेरा अन्य उत्तर देखें।


7

मैं एलन मूर के उत्तर की व्याख्या करना चाहूंगा

एक शब्द सीमा एक ऐसी स्थिति है जो या तो एक शब्द चरित्र से पहले होती है और उसके बाद नहीं होती है या उसके बाद एक शब्द चरित्र होता है और एक से पहले नहीं होता है।

मान लीजिए कि मेरे पास एक स्ट्रिंग है "यह एक सी है एक टी, और वह एक भयानक है", और मुझे लगता है कि सभी घटनाओं (ओं) को अक्षर 'ए' को बदलना चाहिए, यदि यह पत्र "शब्द की सीमा" में मौजूद है , अर्थात a'बिल्ली' के अंदर के अक्षर को नहीं बदलना चाहिए।

तो मैं regex ( पायथन में ) के रूप में प्रदर्शन करूँगा

re.sub("\ba","e", myString.strip())// के aसाथ बदलेंe

इसलिए उत्पादन होगा यह वह जगह है eएक टी end वह के ewesome


5

मैं जब पाठ में खोज शब्द की तरह है के लिए एक भी बदतर समस्या में पड़ गए .NET, C++, C#, और C। आपको लगता होगा कि कंप्यूटर प्रोग्रामर किसी ऐसी भाषा का नाम लेना बेहतर जानते हैं, जिसके लिए नियमित अभिव्यक्ति लिखना कठिन हो।

वैसे भी, यह मुझे पता चला है (संक्षेप में ज्यादातर http : //www. अनियमित-expressions.info , जो एक महान साइट है): रेगेक्स के अधिकांश स्वादों में, जो चरित्र शॉर्ट-हैंड चरित्र वर्ग द्वारा मेल खाते \wहैं वे हैं वर्ण जो शब्द सीमाओं द्वारा शब्द वर्ण के रूप में माने जाते हैं। जावा एक अपवाद है। जावा यूनिकोड का समर्थन करता है \bलेकिन इसके लिए नहीं \w। (मुझे यकीन है कि उस समय इसका एक अच्छा कारण था)।

\w"शब्द चरित्र" के लिए खड़ा है। यह हमेशा ASCII वर्णों से मेल खाता है [A-Za-z0-9_]। अंडरस्कोर और अंकों (लेकिन डैश नहीं!) को शामिल करने पर ध्यान दें। अधिकांश स्वादों में जो यूनिकोड का समर्थन करते हैं, \wउनमें अन्य लिपियों के कई पात्र शामिल हैं। इसमें बहुत सारी विसंगति है कि कौन से पात्र वास्तव में शामिल हैं। वर्णमाला लिपियों और विचारधाराओं के पत्र और अंक आम तौर पर शामिल होते हैं। अंडरस्कोर और संख्यात्मक प्रतीकों के अलावा कनेक्टर विराम चिह्न जो अंक नहीं हैं या शामिल नहीं हो सकते हैं। XML स्कीमा और XPath में भी सभी प्रतीकों को शामिल किया गया है \w। लेकिन जावा, जावास्क्रिप्ट और PCRE केवल ASCII वर्णों के साथ मेल खाते हैं\w

यही कारण है कि जावा-आधारित रेगेक्स खोज करता है C++, C#या .NET(जब आप अवधि और प्लस से बचने के लिए याद करते हैं) द्वारा खराब कर दिया जाता है \b

नोट: मुझे यकीन नहीं है कि पाठ में गलतियों के बारे में क्या करना है, जैसे कि जब किसी ने वाक्य के अंत में एक अवधि के बाद कोई स्थान नहीं रखा है। मैंने इसके लिए अनुमति दी थी, लेकिन मुझे यकीन नहीं है कि यह आवश्यक रूप से सही काम है।

वैसे भी, जावा में, यदि आप उन अजीब-नाम वाली भाषाओं के लिए पाठ खोज रहे हैं, तो आपको \bव्हाट्सएप और विराम चिह्नों से पहले और बाद में इसे बदलने की आवश्यकता है । उदाहरण के लिए:

public static String grep(String regexp, String multiLineStringToSearch) {
    String result = "";
    String[] lines = multiLineStringToSearch.split("\\n");
    Pattern pattern = Pattern.compile(regexp);
    for (String line : lines) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            result = result + "\n" + line;
        }
    }
    return result.trim();
}

फिर अपने परीक्षण या मुख्य कार्य में:

    String beforeWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|^)";   
    String afterWord =  "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|$)";
    text = "Programming in C, (C++) C#, Java, and .NET.";
    System.out.println("text="+text);
    // Here is where Java word boundaries do not work correctly on "cutesy" computer language names.  
    System.out.println("Bad word boundary can't find because of Java: grep with word boundary for .NET="+ grep("\\b\\.NET\\b", text));
    System.out.println("Should find: grep exactly for .NET="+ grep(beforeWord+"\\.NET"+afterWord, text));
    System.out.println("Bad word boundary can't find because of Java: grep with word boundary for C#="+ grep("\\bC#\\b", text));
    System.out.println("Should find: grep exactly for C#="+ grep("C#"+afterWord, text));
    System.out.println("Bad word boundary can't find because of Java:grep with word boundary for C++="+ grep("\\bC\\+\\+\\b", text));
    System.out.println("Should find: grep exactly for C++="+ grep(beforeWord+"C\\+\\+"+afterWord, text));

    System.out.println("Should find: grep with word boundary for Java="+ grep("\\bJava\\b", text));
    System.out.println("Should find: grep for case-insensitive java="+ grep("?i)\\bjava\\b", text));
    System.out.println("Should find: grep with word boundary for C="+ grep("\\bC\\b", text));  // Works Ok for this example, but see below
    // Because of the stupid too-short cutsey name, searches find stuff it shouldn't.
    text = "Worked on C&O (Chesapeake and Ohio) Canal when I was younger; more recently developed in Lisp.";
    System.out.println("text="+text);
    System.out.println("Bad word boundary because of C name: grep with word boundary for C="+ grep("\\bC\\b", text));
    System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
    // Make sure the first and last cases work OK.

    text = "C is a language that should have been named differently.";
    System.out.println("text="+text);
    System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

    text = "One language that should have been named differently is C";
    System.out.println("text="+text);
    System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

    //Make sure we don't get false positives
    text = "The letter 'c' can be hard as in Cat, or soft as in Cindy. Computer languages should not require disambiguation (e.g. Ruby, Python vs. Fortran, Hadoop)";
    System.out.println("text="+text);
    System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

PS मेरा धन्यवाद http://regexpal.com/ जिसके बिना रेगेक्स की दुनिया बहुत दयनीय होगी!


मैं यह समझने की कोशिश कर रहा था कि मैं मैच क्यों नहीं खेल सकता C#लेकिन अब यह स्पष्ट हो गया है
मुगोमा जे। ओकोमा

4

सीमा शर्तों पर प्रलेखन की जाँच करें:

http://java.sun.com/docs/books/tutorial/essential/regex/bounds.html

इस नमूने की जाँच करें:

public static void main(final String[] args)
    {
        String x = "I found the value -12 in my string.";
        System.err.println(Arrays.toString(x.split("\\b-?\\d+\\b")));
    }

जब आप इसे प्रिंट करते हैं, तो ध्यान दें कि आउटपुट यह है:

[मुझे मूल्य मिला - मेरे तार में।]

इसका अर्थ यह है कि "-" वर्ण को किसी शब्द की सीमा पर होने के कारण नहीं उठाया जा रहा है क्योंकि इसे शब्द वर्ण नहीं माना जाता है। ऐसा लगता है जैसे @barianary थोड़े ने मुझे पंच मार दिया, इसलिए उन्हें एक वोट मिला।


2

शब्द सीमा \ b का उपयोग किया जाता है जहां एक शब्द एक शब्द वर्ण और दूसरा एक गैर-शब्द वर्ण होना चाहिए। नकारात्मक संख्या के लिए नियमित अभिव्यक्ति होनी चाहिए

--?\b\d+\b

काम कर रहे DEMO की जाँच करें


1

मेरा मानना ​​है कि आपकी समस्या इस तथ्य के कारण है कि -एक शब्द चरित्र नहीं है। इस प्रकार, शब्द सीमा के बाद मैच होगा- , और इसलिए इसे कैप्चर नहीं करेगी। शब्द सीमाएं पहले और बाद में अंतिम शब्द वर्णों के साथ एक स्ट्रिंग में मेल खाती हैं, साथ ही किसी भी जगह जहां पहले यह एक शब्द चरित्र या गैर-शब्द चरित्र है, और इसके बाद विपरीत है। यह भी ध्यान दें कि शब्द सीमा शून्य-चौड़ाई वाला मेल है।

एक संभव विकल्प है

(?:(?:^|\s)-?)\d+\b

यह अंतरिक्ष वर्ण और वैकल्पिक डैश के साथ शुरू होने वाली किसी भी संख्या से मेल खाएगा, और शब्द सीमा पर समाप्त होगा। यह स्ट्रिंग की शुरुआत में शुरू होने वाली संख्या से भी मेल खाएगा।


0

मुझे लगता है कि यह पिछले मैच या स्ट्रिंग की शुरुआत या अंत की सीमा (यानी चरित्र का अनुसरण) है।


1
आप सोच रहे हैं \G: \Aपहले मैच के प्रयास में स्ट्रिंग की शुरुआत (जैसे ) से मेल खाता है; इसके बाद यह उस स्थिति से मेल खाता है जहां पिछला मैच समाप्त हुआ था।
एलन मूर

0

जब आप \\b(\\w+)+\\bउस शब्द का उपयोग करते हैं जिसका अर्थ केवल शब्द वर्णों वाले शब्द के साथ सटीक मिलान होता है([a-zA-Z0-9])

उदाहरण के लिए आपके मामले \\bमें रेगेक्स की शुरुआत में -12(अंतरिक्ष के साथ) स्वीकार करना होगा लेकिन फिर यह स्वीकार नहीं करेगा -12(अंतरिक्ष के बिना)

मेरे शब्दों का समर्थन करने के लिए संदर्भ के लिए: https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.