regex

2014-12-11 13 views
10

के साथ दो वर्णों के बीच अंतर को भरने के लिए मेरे पास डेटा जैसा सेट है। वांछित.result में दिखाए गए अनुसार, मैं दो बिंदुओं के बीच 1 के बीच सभी बिंदुओं को प्रतिस्थापित करना चाहता हूं। क्या मैं आधार पर regex के साथ ऐसा कर सकता हूं?regex

मैंने कोशिश की:

regexpr("^1\\.1$", my.data$my.string, perl = TRUE) 

यहाँ C#

Characters between two exact characters

किसी भी सुझाव के लिए धन्यवाद में एक समाधान है।

my.data <- read.table(text=' 
    my.string       state 
    ................1...............1. A 
    ......1..........................1 A 
    .............1.....2.............. B 
    ......1.................1...2..... B 
    ....1....2........................ B 
    1...2............................. C 
    ..........1....................1.. C 
    .1............................1... C 
    .................1...........1.... C 
    ........1....2.................... C 
    ......1........................1.. C 
    ....1....1...2.................... D 
    ......1....................1...... D 
    .................1...2............ D 
', header = TRUE, na.strings = 'NA', stringsAsFactors = FALSE) 

desired.result <- read.table(text=' 
    my.string       state 
    ................11111111111111111. A 
    ......1111111111111111111111111111 A 
    .............1.....2.............. B 
    ......1111111111111111111...2..... B 
    ....1....2........................ B 
    1...2............................. C 
    ..........1111111111111111111111.. C 
    .111111111111111111111111111111... C 
    .................1111111111111.... C 
    ........1....2.................... C 
    ......11111111111111111111111111.. C 
    ....111111...2.................... D 
    ......1111111111111111111111...... D 
    .................1...2............ D 
', header = TRUE, na.strings = 'NA', stringsAsFactors = FALSE) 
+0

यह पैटर्न है कि होता था 'regexpr' के साथ एक और अधिक उपयोगी परिणाम दिया है:' "1 \\। * 1" '। '^' और '$' केवल मैचों की अनुमति देगा यदि 1 स्ट्रिंग के दोनों सिरों पर थे (और क्वांटिफ़ायर की कमी केवल स्ट्रिंग से केवल 1 अवधि के साथ मेल खाती है।) –

+0

अपेक्षित परिणाम क्या है जब चार (या अधिक) 1 एक ही पंक्ति पर हैं (यानी '..1 ... 1 ... 1 ... 1..')? '..11111 ... 11111..' या' ..1111111111111..'? –

उत्तर

12

नीचे \G सुविधा और lookaround वक्तव्य दिये gsub का उपयोग कर एक विकल्प है।

> gsub('(?:1|\\G(?<!^))\\K\\.(?=\\.*1)', '1', my.data$my.string, perl = TRUE) 
# [1] "................11111111111111111." "......1111111111111111111111111111" 
# [3] ".............1.....2.............." "......1111111111111111111...2....." 
# [5] "....1....2........................" "1...2............................." 
# [7] "..........1111111111111111111111.." ".111111111111111111111111111111..." 
# [9] ".................1111111111111...." "........1....2...................." 
# [11] "......11111111111111111111111111.." "....111111...2...................." 
# [13] "......1111111111111111111111......" ".................1...2............" 

\G सुविधा एक लंगर है कि दो स्थानों में से एक में से मिलान कर सकते है; अंतिम मैच के अंत में स्ट्रिंग स्थिति या स्थिति की शुरुआत। चूंकि ऐसा लगता है कि आप स्ट्रिंग स्थिति की शुरुआत में बिंदुओं से बचना चाहते हैं, इसलिए हम स्ट्रिंग की शुरुआत को बाहर करने के लिए एक लुकराऊ दावे \G(?<!^) का उपयोग करते हैं।

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

आप एक समग्र ब्रेकडाउन पा सकते हैं जो नियमित अभिव्यक्ति here बताती है।

+1

असाधारण। धन्यवाद।जब आपके पास समय होता है तो कृपया यह बताएं कि यह कैसे काम करता है। –

+6

यह एक बुरा गधा regex है। @ मार्कमिलर, [यहां] देखें (http://rick.measham.id.au/paste/explain.pl?regex=%28%3F%3A1%7C%5CG%28%3F%3C%21%5E%29 % 2 9% 5CK% 5 सी।% 28% 3 एफ% 3 डी। *% 3 एफ 1% 2 9) –

+2

ओएमजी! एक स्वचालित regex- व्याख्याता?! –

5

यहाँ एक विकल्प एक अपेक्षाकृत सरल regex और gregexpr(), regmatches(), और regmatches<-() के मानक संयोजन की पहचान करने के लिए, निकालने, पर काम करते हैं, और फिर उस regex मिलान सबस्ट्रिंग की जगह उपयोग करता है।

## Copy the character vector 
x <- my.data$my.string 
## Find sequences of "."s bracketed on either end by a "1" 
m <- gregexpr("(?<=1)\\.+(?=1)", x, perl=TRUE) 
## Standard template for operating on and replacing matched substrings 
regmatches(x,m) <- sapply(regmatches(x,m), function(X) gsub(".", "1", X)) 

## Check that it worked 
head(x) 
# [1] "................11111111111111111." "......1111111111111111111111111111" 
# [3] ".............1.....2.............." "......1111111111111111111...2....." 
# [5] "....1....2........................" "1...2............................." 
7

gsubfn का उपयोग करना, पहले तर्क के लिए रेगुलर एक्सप्रेशन से मेल खाता है जो 1 है और 1 के बीच वर्ण और बाद कब्जा है।

library(gsubfn) 
transform(my.data, my.string = gsubfn("1(.*)1", ~ gsub(".", 1, x), my.string)) 

अगर वहाँ 1 के एक से अधिक जोड़े हो सकता है एक स्ट्रिंग में तो नियमित रूप "1(.*?)1" का उपयोग करें: दूसरा तर्क एक समारोह है, सूत्र अंकन, जो gsub का उपयोग करता है 1 साथ कब्जा कर लिया स्ट्रिंग में प्रत्येक चरित्र को बदलने के लिए में व्यक्त किया इसके बजाय अभिव्यक्ति।

दृश्य नियमित अभिव्यक्ति यहाँ काफी सरल है कि यह सीधे समझा जा सकता है, लेकिन यहाँ एक debuggex दृश्य anwyays है:

1(.*)1 

Regular expression visualization

Debuggex Demo

+1

इसे जोड़ने के लिए धन्यवाद। मैंने 'gsubfn()' एक त्वरित शॉट दिया था (लुकहेड का उपयोग करके और दावेदार दिखने), लेकिन इसके गैर-पीसीआरई रेगेक्स इंजन द्वारा stymied था। मुझे यह पसंद है कि यह समाधान कैसे साफ करता है। –

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