2009-07-05 12 views
127

मैं कुछ सरल उदाहरणों और एएनएसआई सी man regex.h में नियमित अभिव्यक्तियों का उपयोग करने के सर्वोत्तम अभ्यासों के बाद हूं, जो बहुत मदद नहीं देता है।सी में नियमित अभिव्यक्ति: उदाहरण?

+5

एएनएसआई सी में रेगेक्स के लिए कोई अंतर्निहित समर्थन नहीं है। आप किस रेगेक्स लाइब्रेरी का उपयोग कर रहे हैं? – Joe

+5

[रोब पाइक] (http://en.wikipedia.org/wiki/Rob_Pike) ने एक छोटी नियमित अभिव्यक्ति स्ट्रिंग खोज फ़ंक्शन लिखा जिसने पुस्तक के अभ्यास के लिए नियमित अभिव्यक्तियों का एक बहुत ही उपयोगी सबसेट स्वीकार किया, जिसमें वह और [ब्रायन कर्निघन ] (http://en.wikipedia.org/wiki/Brian_Kernighan) सह-लेखक। इस चर्चा को देखें, एक नियमित अभिव्यक्ति Matcher, डॉ Kernighan द्वारा http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html –

उत्तर

167

नियमित अभिव्यक्ति वास्तव में एएनएसआई सी का हिस्सा नहीं हैं। ऐसा लगता है कि आप POSIX नियमित अभिव्यक्ति लाइब्रेरी के बारे में बात कर रहे हैं, जो अधिकांश (सभी?) * निक्स के साथ आता है। काफी है कि है

#include <regex.h>   
regex_t regex; 
int reti; 
char msgbuf[100]; 

/* Compile regular expression */ 
reti = regcomp(&regex, "^a[[:alnum:]]", 0); 
if (reti) { 
    fprintf(stderr, "Could not compile regex\n"); 
    exit(1); 
} 

/* Execute regular expression */ 
reti = regexec(&regex, "abc", 0, NULL, 0); 
if (!reti) { 
    puts("Match"); 
} 
else if (reti == REG_NOMATCH) { 
    puts("No match"); 
} 
else { 
    regerror(reti, &regex, msgbuf, sizeof(msgbuf)); 
    fprintf(stderr, "Regex match failed: %s\n", msgbuf); 
    exit(1); 
} 

/* Free memory allocated to the pattern buffer by regcomp() */ 
regfree(&regex); 

वैकल्पिक रूप से, आप PCRE, सी पर्ल वाक्य रचना में पर्ल संगत नियमित अभिव्यक्ति के लिए एक पुस्तकालय की जाँच कर सकते हैं: यहाँ (this के आधार पर) सी में POSIX regexes का उपयोग करने का एक उदाहरण है जावा, पायथन, और कई अन्य भाषाओं में उपयोग किया गया एक ही वाक्यविन्यास। POSIX वाक्य रचना वाक्य रचना, grep, sed, vi द्वारा प्रयोग किया जाता है आदि

+4

जब तक आप निर्भरता से बचने की आवश्यकता नहीं है I दूसरा पीसीआरई, यह है कुछ अच्छे वाक्यविन्यास संवर्धन और बहुत स्थिर है। कम से कम लिनक्स के पुराने संस्करणों के साथ, "अंतर्निहित" नियमित अभिव्यक्ति लाइब्रेरी को कुछ इनपुट स्ट्रिंग्स और कुछ नियमित अभिव्यक्तियों को क्रैश करना बहुत कठिन नहीं होता है जो "लगभग" मेल खाते हैं या बहुत से विशेष पात्रों को शामिल करते हैं – bdk

+0

@Laurence क्या अर्थ है regcomp करने के लिए 0 गुजरने के? regcomp केवल 4 पूर्ण मोड का प्रतिनिधित्व करने के लिए चार पूर्णांक मान 1, 2, 4 और 8 लेता है। – lixiang

+2

@lixiang 'regcomp', 'cflags' के लिए अंतिम पैरामीटर, बिटमैस्क है। Http://pubs.opengroup.org/onlinepubs/009695399/functions/regcomp से।एचटीएमएल: "सीएफएलएजी तर्क बिटवाई-समावेशी है या निम्न झंडे के शून्य या अधिक ..."। यदि आप OR-साथ शून्य करते हैं, तो आपको 0 मिल जाएगा। मुझे लगता है कि 'regcomp' के लिए लिनक्स मैनपेज कहता है, "cflags थोड़ा सा हो सकता है- या निम्न में से एक या अधिक", जो भ्रामक प्रतीत होता है। –

9

यह शायद आप क्या चाहते हैं नहीं है, लेकिन re2c जैसे उपकरण एएनएसआई सी POSIX (-ish) संकलन कर सकते हैं नियमित अभिव्यक्ति यह एक स्थानापन्न के रूप में लिखा है lex के लिए, लेकिन यह दृष्टिकोण आपको गति की आखिरी बिट के लिए लचीलापन और सुगमता बलिदान देने की अनुमति देता है, अगर आपको वास्तव में इसकी आवश्यकता है।

3

man regex.h रिपोर्ट्स regex.h के लिए कोई मैन्युअल प्रविष्टि नहीं है, लेकिन man 3 regex आपको पैटर्न मिलान के लिए POSIX फ़ंक्शंस समझाते हुए एक पृष्ठ देता है।

उसी कार्य को The GNU C Library: Regular Expression Matching में वर्णित किया गया है, जहां यह समझाया गया है कि जीएनयू सी लाइब्रेरी दोनों POSIX.2 इंटरफ़ेस का समर्थन करता है, और जीएनयू सी लाइब्रेरी में कई सालों से इसका समर्थन होता है।

उदाहरण के लिए

, एक निम्नलिखित एक काल्पनिक कार्यक्रम है कि प्रिंट जो तार तर्क के रूप में पारित कर दिया की तर्ज पहला तर्क के रूप में पारित मैच, आप के समान कोड का उपयोग कर के लिए:

#include <errno.h> 
#include <regex.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void print_regerror (int errcode, size_t length, regex_t *compiled); 

int 
main (int argc, char *argv[]) 
{ 
    regex_t regex; 
    int result; 

    if (argc < 3) 
    { 
     // The number of passed arguments is lower than the number of 
     // expected arguments. 
     fputs ("Missing command line arguments\n", stderr); 
     return EXIT_FAILURE; 
    } 

    result = regcomp (&regex, argv[1], REG_EXTENDED); 
    if (result) 
    { 
     // Any value different from 0 means it was not possible to 
     // compile the regular expression, either for memory problems 
     // or problems with the regular expression syntax. 
     if (result == REG_ESPACE) 
     fprintf (stderr, "%s\n", strerror(ENOMEM)); 
     else 
     fputs ("Syntax error in the regular expression passed as first argument\n", stderr); 
     return EXIT_FAILURE;    
    } 
    for (int i = 2; i < argc; i++) 
    { 
     result = regexec (&regex, argv[i], 0, NULL, 0); 
     if (!result) 
     { 
      printf ("'%s' matches the regular expression\n", argv[i]); 
     } 
     else if (result == REG_NOMATCH) 
     { 
      printf ("'%s' doesn't the regular expression\n", argv[i]); 
     } 
     else 
     { 
      // The function returned an error; print the string 
      // describing it. 
      // Get the size of the buffer required for the error message. 
      size_t length = regerror (result, &regex, NULL, 0); 
      print_regerror (result, length, &regex);  
      return EXIT_FAILURE; 
     } 
    } 

    /* Free the memory allocated from regcomp(). */ 
    regfree (&regex); 
    return EXIT_SUCCESS; 
} 

void 
print_regerror (int errcode, size_t length, regex_t *compiled) 
{ 
    char buffer[length]; 
    (void) regerror (errcode, compiled, buffer, length); 
    fprintf(stderr, "Regex match failed: %s\n", buffer); 
} 

regcomp() के अंतिम तर्क कम से कम REG_EXTENDED होने की आवश्यकता है, या फ़ंक्शन basic regular expressions का उपयोग करेंगे, जिसका अर्थ है कि (उदाहरण के लिए) आपको a{3} के बजाय extended regular expressions से उपयोग किया जाना चाहिए, जो शायद आप उपयोग करने की अपेक्षा करते हैं।

POSIX.2 में वाइल्डकार्ड मिलान के लिए एक और फ़ंक्शन भी है: fnmatch()। यह नियमित अभिव्यक्ति को संकलित करने की अनुमति नहीं देता है, या उप-अभिव्यक्ति से मेल खाने वाले सबस्ट्रिंग प्राप्त करने की अनुमति नहीं देता है, लेकिन यह जांचने के लिए बहुत विशिष्ट है कि फ़ाइल नाम वाइल्डकार्ड से मेल खाता है (उदा। यह FNM_PATHNAME ध्वज का उपयोग करता है)।

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