2014-12-11 4 views
10

다음과 같은 데이터 세트가 있습니다. desired.result와 같이 2 개의 1과 1 사이의 모든 점을 1로 바꾸고 싶습니다. 기왕 Rregex으로이 작업을 수행 할 수 있습니까? 두 문자 사이의 간격을 정규식으로 채우는 방법

내가 시도 :

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

Characters between two exact characters

어떤 제안 주셔서 감사합니다 C#에서 솔루션입니다.

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

이 그 것 패턴이었다

시각화 여기 정규 표현식은 debuggex 시각화 anwyays이 직접적으로 이해 될 수있을만큼 간단하지만 여기에있다 'regexpr' :''1 \\. * 1 "'에 더 유용한 결과를주었습니다. '^'와'$'는 1이 문자열의 양쪽 끝에있을 경우에만 일치를 허용합니다 (한정 기호가 없으면 1 개의 마침표 만있는 문자열과 만 일치합니다). –

+0

4 개 (또는 more) 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 기능은 두 위치 중 하나에 일치 할 수있는 앵커; 문자열 위치의 시작 또는 마지막 일치 항목의 끝 위치. 문자열 위치의 시작 부분에서 점을 사용하지 않으려 고하는 것으로 보아서 lookaround 어설 션 \G(?<!^)을 사용하여 문자열의 시작 부분을 제외시킵니다.

\K 에스 케이프 시퀀스는보고 된 일치 항목의 시작점을 재설정하고 이전에 소비 된 문자는 더 이상 포함되지 않습니다.

정규식 here을 설명하는 전반적인 분석을 찾을 수 있습니다.

+1

특별합니다. 고맙습니다.시간이있을 때 이것이 어떻게 작동하는지에 대한 설명을 게시하는 것을 고려하십시오. –

+6

이것은 나쁜 엉덩이 정규식입니다. @MarkMiller, [here] (http://rick.measham.id.au/paste/explain.pl?regex=%28%3F%3A1%7C%5CG%28%3F%3C%21%5E%29 참조) % 29 % 5CK % 5C. % 28 % 3F % 3D. * % 3F1 % 29) –

+2

OMG! 자동화 된 regex-explainer?!? –

5

다음은 비교적 간단한 정규식과 gregexpr(), regmatches()regmatches<-()의 표준 조합을 사용하여 해당 정규 표현식과 일치하는 부분 문자열을 식별, 추출, 작동 및 교체하는 옵션입니다. gsubfn를 사용

## 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

는 첫 번째 인수는 일치하는 1과 1의 사이의 캐릭터와 후자를 캡처하는 정규 표현식입니다. 문자열 (1 개)의 복수의 쌍이있을 수 있다면

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

후 정기적으로 "1(.*?)1"을 사용 번째 인수는 함수이고, 1 포착 문자열의 각 문자를 대체 gsub 사용 식 표기법으로 표현 표현 대신.

1(.*)1 

Regular expression visualization

Debuggex Demo

+1

추가해 주셔서 감사합니다. 나는'gsubfn()'에 (lookahead와 lookbehind 어설 션을 사용하여) 빠른 샷을 주었지만, PCRE가 아닌 정규식 엔진에 의해 곤란을 겪었다. 나는 이것이 해결책을 만드는 방법을 좋아한다. –

관련 문제