C++
नियमित अभिव्यक्ति
खोज…
परिचय
रेग्युलर एक्सप्रेशंस (कभी-कभी रेक्सक्स या रेग्जैक्स कहलाते हैं) एक टेक्स्ट सिंटैक्स होता है, जो उन पैटर्नों का प्रतिनिधित्व करता है, जो कि संचालित स्ट्रिंग्स में मेल खा सकते हैं।
C ++ 11 में पेश किए गए रेगुलर एक्सप्रेशंस वैकल्पिक रूप से मिलान किए गए स्ट्रिंग्स के एक रिटर्न ऐरे का समर्थन कर सकते हैं या किसी अन्य टेक्स्टुअल सिंटैक्स को परिभाषित कर सकते हैं कि कैसे संचालित स्ट्रिंग्स में मिलान किए गए पैटर्न को प्रतिस्थापित किया जाए।
वाक्य - विन्यास
- regex_match // पूर्ण वर्ण अनुक्रम regex द्वारा मिलान किया गया था या नहीं, रिटर्न, वैकल्पिक रूप से एक मैच ऑब्जेक्ट में कैप्चर करना
- regex_search // रिटर्न अनुक्रम चरित्र के एक हिस्से को regex द्वारा मिलान किया गया था या नहीं, वैकल्पिक रूप से एक मैच ऑब्जेक्ट में कैप्चर करना
- regex_replace // इनपुट कैरेक्टर अनुक्रम को एक रीप्जेक्स द्वारा एक रिप्लेसमेंट फॉर्मेट स्ट्रिंग द्वारा संशोधित करके लौटाता है
- regex_token_iterator // पुनरावृत्तियों द्वारा परिभाषित वर्ण अनुक्रम की सूची के साथ प्रारंभ किया गया एक चरित्र अनुक्रम के साथ प्रारंभ, और एक regex। डेरेफ्रेंसिंग रेगेक्स के वर्तमान में अनुक्रमित मैच को लौटाता है। अगले कैप्चर इंडेक्स में वृद्धि बढ़ जाती है या यदि वर्तमान में अंतिम इंडेक्स पर है, तो इंडेक्स को रीसेट करता है और चरित्र अनुक्रम में रेगेक्स मैच की अगली घटना को याद दिलाता है
- regex_iterator // पुनरावृत्तियों द्वारा परिभाषित वर्ण अनुक्रम और एक regex के साथ प्रारंभ। डेरेफ्रेंसिंग चरित्र अनुक्रम के हिस्से को पूरा करता है जो वर्तमान में पूरे रेगेक्स से मेल खाता है। इंक्रीमेंटिंग चरित्र अनुक्रम में रेगेक्स मैच की अगली घटना को ढूंढता है
पैरामीटर
हस्ताक्षर | विवरण |
---|---|
bool regex_match(BidirectionalIterator first, BidirectionalIterator last, smatch& sm, const regex& re, regex_constraints::match_flag_type flags) | BidirectionalIterator किसी भी चरित्र इटरेटर कि वेतन वृद्धि और घटती ऑपरेटरों प्रदान करता है smatch हो सकता है cmatch या के किसी भी अन्य अन्य संस्करण match_results कि के प्रकार स्वीकार करता है BidirectionalIterator smatch तर्क regex के परिणाम रिटर्न की जरूरत नहीं होती है, तो चाहे लोप किया जा सकता है re पूरे चरित्र से मेल खाता है अनुक्रम first और last द्वारा परिभाषित |
bool regex_match(const string& str, smatch& sm, const regex re&, regex_constraints::match_flag_type flags) | string हो सकता है या तो एक const char* या एक एल मूल्य string , कार्य एक आर-मूल्य को स्वीकार string स्पष्ट रूप से नष्ट हो जाती हैं smatch हो सकता है cmatch या के किसी भी अन्य अन्य संस्करण match_results कि के प्रकार स्वीकार करता है str smatch तर्क अगर लोप किया जा सकता है regex के परिणाम रिटर्न आवश्यक नहीं हैं कि क्या re मेल खाता है पूरे चरित्र अनुक्रम द्वारा परिभाषित str |
मूल regex_match और regex_search उदाहरण
const auto input = "Some people, when confronted with a problem, think \"I know, I'll use regular expressions.\""s;
smatch sm;
cout << input << endl;
// If input ends in a quotation that contains a word that begins with "reg" and another word begining with "ex" then capture the preceeding portion of input
if (regex_match(input, sm, regex("(.*)\".*\\breg.*\\bex.*\"\\s*$"))) {
const auto capture = sm[1].str();
cout << '\t' << capture << endl; // Outputs: "\tSome people, when confronted with a problem, think\n"
// Search our capture for "a problem" or "# problems"
if(regex_search(capture, sm, regex("(a|d+)\\s+problems?"))) {
const auto count = sm[1] == "a"s ? 1 : stoi(sm[1]);
cout << '\t' << count << (count > 1 ? " problems\n" : " problem\n"); // Outputs: "\t1 problem\n"
cout << "Now they have " << count + 1 << " problems.\n"; // Ouputs: "Now they have 2 problems\n"
}
}
regex_replace उदाहरण
यह कोड विभिन्न ब्रेस स्टाइल में लेता है और उन्हें एक ट्रू ब्रेस स्टाइल में परिवर्तित करता है:
const auto input = "if (KnR)\n\tfoo();\nif (spaces) {\n foo();\n}\nif (allman)\n{\n\tfoo();\n}\nif (horstmann)\n{\tfoo();\n}\nif (pico)\n{\tfoo(); }\nif (whitesmiths)\n\t{\n\tfoo();\n\t}\n"s;
cout << input << regex_replace(input, regex("(.+?)\\s*\\{?\\s*(.+?;)\\s*\\}?\\s*"), "$1 {\n\t$2\n}\n") << endl;
regex_token_iterator उदाहरण
एक std::regex_token_iterator
कॉमा सेपरेटेड वैल्यू फ़ाइल के तत्वों को निकालने के लिए एक जबरदस्त टूल प्रदान करता है। पुनरावृति के फायदों के अलावा, यह पुनरावृत्त भागे हुए अल्पविरामों को पकड़ने में सक्षम है जहाँ अन्य विधियाँ संघर्ष करती हैं:
const auto input = "please split,this,csv, ,line,\\,\n"s;
const regex re{ "((?:[^\\\\,]|\\\\.)+)(?:,|$)" };
const vector<string> m_vecFields{ sregex_token_iterator(cbegin(input), cend(input), re, 1), sregex_token_iterator() };
cout << input << endl;
copy(cbegin(m_vecFields), cend(m_vecFields), ostream_iterator<string>(cout, "\n"));
रेगेक्स पुनरावृत्तियों के साथ एक उल्लेखनीय गोटा है, regex
तर्क एक एल-मूल्य होना चाहिए। एक R- मान काम नहीं करेगा ।
regex_iterator उदाहरण
जब regex_iterator
की regex_iterator
को पुनरावृत्त करना regex_iterator
है तो regex_iterator
एक अच्छा विकल्प है। एक अपसंदर्भन regex_iterator
एक रिटर्न match_result
। यह सशर्त कैप्चर या कैप्चर के लिए बहुत अच्छा है जिसमें अन्योन्याश्रयता है। मान लीजिए कि हम कुछ C ++ कोड को टोकन देना चाहते हैं। दिया हुआ:
enum TOKENS {
NUMBER,
ADDITION,
SUBTRACTION,
MULTIPLICATION,
DIVISION,
EQUALITY,
OPEN_PARENTHESIS,
CLOSE_PARENTHESIS
};
हम इस स्ट्रिंग को टोकन कर सकते हैं: const auto input = "42/2 + -8\t=\n(2 + 2) * 2 * 2 -3"s
इस तरह से एक regex_iterator
साथ:
vector<TOKENS> tokens;
const regex re{ "\\s*(\\(?)\\s*(-?\\s*\\d+)\\s*(\\)?)\\s*(?:(\\+)|(-)|(\\*)|(/)|(=))" };
for_each(sregex_iterator(cbegin(input), cend(input), re), sregex_iterator(), [&](const auto& i) {
if(i[1].length() > 0) {
tokens.push_back(OPEN_PARENTHESIS);
}
tokens.push_back(i[2].str().front() == '-' ? NEGATIVE_NUMBER : NON_NEGATIVE_NUMBER);
if(i[3].length() > 0) {
tokens.push_back(CLOSE_PARENTHESIS);
}
auto it = next(cbegin(i), 4);
for(int result = ADDITION; it != cend(i); ++result, ++it) {
if (it->length() > 0U) {
tokens.push_back(static_cast<TOKENS>(result));
break;
}
}
});
match_results<string::const_reverse_iterator> sm;
if(regex_search(crbegin(input), crend(input), sm, regex{ tokens.back() == SUBTRACTION ? "^\\s*\\d+\\s*-\\s*(-?)" : "^\\s*\\d+\\s*(-?)" })) {
tokens.push_back(sm[1].length() == 0 ? NON_NEGATIVE_NUMBER : NEGATIVE_NUMBER);
}
रेगेक्स पुनरावृत्तियों के साथ एक उल्लेखनीय गोटा यह है कि regex
तर्क में एक एल-मूल्य होना चाहिए, एक आर-मूल्य काम नहीं करेगा: विज़ुअल स्टूडियो regex_iterator बग?
एक तार को विभाजित करना
std::vector<std::string> split(const std::string &str, std::string regex)
{
std::regex r{ regex };
std::sregex_token_iterator start{ str.begin(), str.end(), r, -1 }, end;
return std::vector<std::string>(start, end);
}
split("Some string\t with whitespace ", "\\s+"); // "Some", "string", "with", "whitespace"
परिमाणकों
मान लीजिए कि हमें एक फ़ोन नंबर के रूप में मान्य const string input
दिया गया है। हम एक शून्य या अधिक क्वांटिफायर के साथ एक संख्यात्मक इनपुट की आवश्यकता द्वारा शुरू कर सकते हैं: regex_match(input, regex("\\d*"))
या एक या एक से अधिक क्वांटिफायर : regex_match(input, regex("\\d+"))
लेकिन यदि input
में कोई अमान्य संख्यात्मक स्ट्रिंग है, तो दोनों वास्तव में कम हो जाते हैं जैसे: "123" चलो यह सुनिश्चित करने के लिए कि हम कम से कम 7 अंक प्राप्त कर रहे हैं, एक n या अधिक मात्रा का उपयोग करें:
regex_match(input, regex("\\d{7,}"))
यह गारंटी देगा कि हम कम से कम एक फोन नंबर प्राप्त करेंगे, लेकिन input
में एक संख्यात्मक स्ट्रिंग भी हो सकती है जो बहुत लंबा है: "123456789012"। तो चलिए n और m क्वांटिफायर के बीच चलते हैं ताकि input
कम से कम 7 अंकों का हो लेकिन 11 से अधिक न हो:
regex_match(input, regex("\\d{7,11}"));
यह हमें करीब आता है, लेकिन [7, 11] की श्रेणी में आने वाले अवैध संख्यात्मक तार अभी भी स्वीकार किए जाते हैं, जैसे: "123456789" तो चलिए देश को एक आलसी मात्रा के साथ वैकल्पिक बनाते हैं:
regex_match(input, regex("\\d?\\d{7,10}"))
यह ध्यान रखना महत्वपूर्ण है कि आलसी क्वांटिफायर संभव के रूप में कुछ वर्णों से मेल खाता है , इसलिए इस चरित्र से मेल खाने का एकमात्र तरीका है यदि पहले से ही 10 वर्ण हैं जो \d{7,10}
से मेल खाते हैं। (पहले किरदार का लालच करने के लिए हमें करना होगा: \d{0,1}
।) आलसी क्वांटिफायर को किसी अन्य क्वांटिफायर में जोड़ा जा सकता है।
अब, हम क्षेत्र कोड को कैसे वैकल्पिक बनाएंगे और केवल एक देश कोड स्वीकार करेंगे यदि क्षेत्र कोड मौजूद था?
regex_match(input, regex("(?:\\d{3,4})?\\d{7}"))
इस अंतिम रेगेक्स में, \d{7}
को 7 अंकों की आवश्यकता होती है । ये 7 अंक वैकल्पिक रूप से 3 या 4 अंकों से पहले हैं।
ध्यान दें कि हमने आलसी परिमाणक को जोड़ा नहीं था: , \d{3,4}?\d{7}
\d{3,4}?
3 या 4 अक्षरों से मेल खाता होगा, पसंद करते हैं। 3. इसके बजाय हम गैर-कैप्चरिंग ग्रुप मैच को एक बार में बना रहे हैं, मैच नहीं करना पसंद करते हैं। एक बेमेल होने के कारण यदि input
में क्षेत्र कोड शामिल नहीं है जैसे: "1234567"।
क्वांटिफायर विषय के निष्कर्ष में, मैं अन्य अपीलीय क्वांटिफायर का उल्लेख करना चाहूंगा जिनका आप उपयोग कर सकते हैं, जिसके पास मात्रात्मक मात्रात्मक है । या तो आलसी क्वांटिफायर या किसी भी क्वांटिफायर को पास किया जा सकता है। अपने पास रखने वाले मात्रात्मक एकमात्र फ़ंक्शन को रेगेक्स इंजन की सहायता करके यह बताना है कि लालच इन पात्रों को लेता है और यदि रेगेक्स विफल होने का कारण बनता है, तो भी उन्हें कभी न दें । उदाहरण के लिए यह बहुत मायने नहीं रखता है: regex_match(input, regex("\\d{3,4}+\\d{7}))
क्योंकि ऐसा input
:" 1234567890 " \d{3,4}+
रूप में मेल नहीं खाएगा \d{3,4}+
हमेशा 4 वर्णों से मेल खाएगा भले ही 3 मिलान ने रेगेक्स को सफल होने दिया हो।
जब मात्रा निर्धारित टोकन परिपक्व पात्रों की संख्या को सीमित करता है, तो सबसे अधिक मात्रात्मक मात्रा का उपयोग किया जाता है। उदाहरण के लिए:
regex_match(input, regex("(?:.*\\d{3,4}+){3}"))
मिलान करने के लिए उपयोग किया जा सकता है यदि input
में निम्न में से कोई भी हो:
1 2 3 4 5 6 7 8 9 0
123-456-7890
(123)456-7890
(1 2 3 4 5 6 7 8 9 0
लेकिन जब यह रेगीक्स वास्तव में चमकता है जब input
में एक अवैध इनपुट होता है:
1 2 3 4 5 6 7 8 9 0
प्रॉपर्टीज क्वांटिफायर के बिना रेगेक्स इंजन को वापस जाना पड़ता है और प्रत्येक संयोजन का परीक्षण करना पड़ता है .*
और या तो 3 या 4 वर्ण यह देखने के लिए कि क्या यह मैच्योर कॉम्बिनेशन पा सकता है। प्रॉपर्टीज क्वांटिफायर के साथ रेगेक्स शुरू होता है जहां 2 एन डी के पास क्वांटिफायर छूट जाता है, '0' वर्ण, और रेगेक्स इंजन समायोजित करने की कोशिश करता है .*
मिलान करने के लिए \d{3,4}
को अनुमति देने के लिए; जब यह रेगेक्स बस विफल नहीं हो सकता है, तो पहले देखने के लिए कोई बैक ट्रैकिंग नहीं की जाती है .*
समायोजन एक मैच की अनुमति दे सकता था।
लंगर
C ++ केवल 4 एंकर प्रदान करता है:
-
^
जो स्ट्रिंग की शुरुआत का दावा करता है -
$
जो स्ट्रिंग के अंत का दावा करता है -
\b
जो a\W
वर्ण या स्ट्रिंग की शुरुआत या अंत का दावा करता है -
\B
जो एक\w
वर्ण का दावा करता है
आइए कहते हैं, उदाहरण के लिए हम इसे के संकेत के साथ एक नंबर पर कब्जा करना चाहते हैं:
auto input = "+1--12*123/+1234"s;
smatch sm;
if(regex_search(input, sm, regex{ "(?:^|\\b\\W)([+-]?\\d+)" })) {
do {
cout << sm[1] << endl;
input = sm.suffix().str();
} while(regex_search(input, sm, regex{ "(?:^\\W|\\b\\W)([+-]?\\d+)" }));
}
यहाँ एक महत्वपूर्ण बात यह है कि लंगर किसी भी पात्र का उपभोग नहीं करता है।