2012-08-10 12 views
9

द्वारा मिलान की गई स्ट्रिंग में किसी विशेष वर्ण के मैचों की संख्या की गणना करें क्या मैं regex में मिलान किए गए प्रत्येक अलग-अलग वर्ण की गणना कर सकता हूं?एक रेगेक्स वाइल्डकार्ड

मान लीजिए regex चला जाता है />(.*)[^a]+/

तरह लग रहा है मैं की घटनाओं की गणना कर सकते हैं, का कहना है कि स्ट्रिंग में पत्र p समूह (.*) द्वारा कब्जा कर लिया?

उत्तर

3

AFAIK, आप नहीं कर सकते। आप केवल कुछ समूह कोष्ठक द्वारा कैप्चर कर सकते हैं और बाद में उस समूह द्वारा कैप्चर किए गए डेटा की लंबाई की जांच कर सकते हैं।

+3

हाँ! * के लिए पांच अपवॉट * आप नहीं कर सकते हैं। मुझे कड़ी मेहनत करनी चाहिए! – Borodin

+0

रेगेक्स के भीतर पूरी तरह से करना संभव है। मेरा जवाब देखें – ikegami

+0

नकारात्मक में "AFAIK" उत्तर मूल रूप से हमेशा खराब पोस्टिंग विकल्प होता है। यदि आप यह समझा नहीं सकते कि यह असंभव क्यों है, तो उन्हें क्यों बताएं कि आपको लगता है? – Mark

5

आपको स्ट्रिंग मिलान और इसे अलग से संसाधित करना होगा।

इस कोड को दर्शाता है

use strict; 
use warnings; 

my $str = '> plantagenetgoosewagonattributes'; 

if ($str =~ />(.*)[^a]+/) { 
    my $substr = $1; 
    my %counts; 
    $counts{$_}++ for $substr =~ /./g; 
    print "'$_' - $counts{$_}\n" for sort keys %counts; 
} 

उत्पादन

' ' - 1 
'a' - 4 
'b' - 1 
'e' - 4 
'g' - 3 
'i' - 1 
'l' - 1 
'n' - 3 
'o' - 3 
'p' - 1 
'r' - 1 
's' - 1 
't' - 5 
'u' - 1 
'w' - 1 
0

पहले एक टिप्पणी: * के लालच के कारण, पिछले [^a]+ एक से अधिक गैर-एक चरित्र से मेल खाते हैं कभी नहीं होगा - यानी, आप + भी छोड़ सकते हैं।

और जैसा कि @ एमवीएफ ने कहा, आपको उस स्ट्रिंग को कैप्चर करने की आवश्यकता है जो वाइल्डकार्ड मैचों में वर्णों को गिनने में सक्षम हो। पर्ल नियमित अभिव्यक्तियों के पास एक विशिष्ट समूह मिलान कितनी बार गिनती करने का कोई तरीका नहीं है - इंजन शायद {,n} तंत्र का समर्थन करने के लिए संख्या को रखता है, लेकिन आप इसे प्राप्त नहीं कर सकते हैं।

2

प्रयोगात्मक, नहींं-उपयोग-मुझे, (?{ code }) निर्माण ...

man perlre से है:

"({कोड}?)" चेतावनी: यह विस्तारित नियमित अभिव्यक्ति सुविधा प्रयोगात्मक माना जाता है, और बिना किसी सूचना के बदला जा सकता है। कोड निष्पादित किया गया है कि साइड इफेक्ट्स रेगेक्स इंजन में भावी ऑप्टिमाइज़ेशन के प्रभाव के कारण संस्करण से संस्करण तक समान रूप से निष्पादित नहीं कर सकते हैं।

है कि आप बंद डरा नहीं किया, तो यहाँ एक उदाहरण है कि "पी" रों regex के

my $p_count; 
">pppppbca" =~ /(?{ $p_count = 0 })>(p(?{$p_count++})|.)*[^a]+/; 
print "$p_count\n"; 
+0

गलत परिणाम उत्पन्न करता है क्योंकि आपने बैकट्रैकिंग के लिए खाता नहीं लिया था। ('Ppppp' और 'pppppa' के लिए 4 लौटाएं, लेकिन रिटर्न 5.) – ikegami

+0

इसके अलावा,' (? {}) के बाहर' '? {}) 'के बाहर घोषित' my' चर का उपयोग करके गलत परिणाम होंगे कुछ स्थितियों में। 'My' के बजाय 'स्थानीय हमारे' का प्रयोग करें। – ikegami

+0

दोनों अच्छे अंक। मैं मानता हूं कि मैंने कभी भी इस सुविधा का उपयोग नहीं किया जब तक कि मैंने इस उदाहरण को लिखने की कोशिश नहीं की। मैंने बैकट्रैकिंग को संभालने के लिए स्थानीय का उपयोग करने के बारे में नोट देखा था। मुझे यकीन नहीं है कि मैंने यह जवाब क्यों पोस्ट किया; मैं इसका उपयोग करने की सिफारिश नहीं करता, लेकिन सोचा कि यह इंगित करने के लिए काफी दिलचस्प था। – chepner

5

बाहर की संख्या की गणना है:

my $p_count = map /p/g, />(.*)[^a]/; 

स्व निहित:

local our $p_count; 
/
    (?{ 0 }) 
    > 
    (?: p (?{ $^R + 1 }) 
    | [^p] 
    )* 
    [^a] 
    (?{ $p_count = $^R; }) 
/x; 

दोनों मामलों में, आप आसानी से सभी अक्षरों को गिनने के लिए इसका विस्तार कर सकते हैं ।

let count=0 
testarray=(a b c d e f g h i j k l m n o p q r s t u v w x y z) 

string="> plantagenetgoosewagonattributes"     # the string 
pattern=">(.*)[^a]+"         # regex pattern 

limitvar=${#testarray[@]}         #array length 

[[ $string =~ $pattern ]] && 
(while [ $count -lt $limitvar ] ; do sub="${BASH_REMATCH[1]//[^${testarray[$count]}]}" ; echo "${testarray[$count]} = ${#sub}" ; ((count++)) ; done) 

बैश 3 से घूर: उदाहरण के लिए,

my %counts; 
if (my ($seq = />(.*)[^a]/) { 
    ++$counts{$_} for split //, $seq; 
} 

my $p_count = $counts{'p'}; 
+0

पर्ल के बाहर अपना 'स्वयं निहित' कोड चलाने का प्रयास करें :) (sed, awk, bash - लेखक टैग देखें)। ;) Regexp के साथ Regexp के 'विस्तारित' वाक्यविन्यास के अंदर कुछ perl कोड चलाने की क्षमता को गड़बड़ न करें। – mvf

+1

@ एमवीएफ, यह असंभव है * उन सभी दुभाषियों में चलने वाली समस्या लिखना असंभव है, जिससे कोई समझ नहीं आता है। (* - आप एक "क्विन" लिख सकते हैं, लेकिन इसमें प्रोग्राम को कई भाषाओं में भी शामिल करना शामिल होगा।) – ikegami

3

Borodin के समाधान की तर्ज पर जा रहे हैं, यहाँ एक शुद्ध बैश से एक है।0, बैश ने कैप्चर समूह पेश किए हैं जिन्हें BASH_REMATCH [n] के माध्यम से एक्सेस किया जा सकता है।

समाधान वर्णों को सरणी के रूप में गिने जाने के लिए घोषित करता है [जटिल मामलों में सरणी घोषणा के लिए declare -a देखें]। एक सिंगल कैरेक्टर गिनती के लिए कोई गिनती वैरिएबल की आवश्यकता नहीं होगी, निर्माण के दौरान नहीं बल्कि सरणी के बजाय चरित्र के लिए एक चर।

यदि आप ऊपर दिए गए कोड में श्रेणियां शामिल हैं, तो यह सरणी घोषणा सही चीज़ करती है।

testarray=(`echo {a..z}`) 

एक if पाश की एक परिचय 0 गिनती पात्रों के प्रदर्शन के लिए खाते में जाएगा। मैं समाधान को यथासंभव सरल रखना चाहता था।