2013-04-09 9 views
6

Öğrenme ifadesine gerçekten zaman ayırıyorum ve farklı oyuncak senaryolarıyla oynuyorum. Çalışamadığım bir kurulum no'lu dizgenin başlangıcından bir karakterin başlangıcına kadar n karakterinin n olmasıyla n> 1'dir.regex karakterinin başlangıcından n 'a geçmesi

Burada, dizenin başlangıcından ilk alt çizgiye geçebilirim. Bunu ikinci veya üçüncü alt çizgiye genelleştiremiyorum.

x <- c("a_b_c_d", "1_2_3_4", "<_?_._:") 

gsub("_.*$", "", x) 

Here's what I'm trying to achieve with regex. (`sub`/`gsub`): 

## > sapply(lapply(strsplit(x, "_"), "[", 1:2), paste, collapse="_") 
## [1] "a_b" "1_2" "<_?" 

#or 

## > sapply(lapply(strsplit(x, "_"), "[", 1:3), paste, collapse="_") 
## [1] "a_b_c" "1_2_3" "<_?_." 

İlgili mesaj: regex from first character to the end of the string

cevap

3

ne dersiniz:

Alternatif
gsub('^(.+_.+?).*$', '\\1', x) 
# [1] "a_b" "1_2" "<_?" 

Eğer tekrar sayısını belirtmek için {} kullanabilirsiniz ...

Yani
sub('((.+_){1}.+?).*$', '\\1', x) # {0} will give "a", {1} - "a_b", {2} - "a_b_c" and so on 

Eğer n'inci biriyle eşleşmesi istiyorsa kendini tekrarlamak zorunda değilsiniz ...

+2

ikinci normal ifade, bir '. +? ve 'alt olmalıdır ('((. + _) {2}. +?). * $', '\\ 1', x)' – eddi

+0

eksik @eddi ikinci regex eksik değildi çünkü nasıl düzgün çalışacağını bilmiyordum! Ve benim düşünceme daha yakın olacağını düşünüyorum. Beni doğru yöne işaret ettiğin için teşekkürler. – Justin

+1

'. +' Before '?' Olmadan, OP'in örnekleriyle eşleşmeyen bir ekstra '_ 'elde edersiniz. – eddi

1

ikinci perl tarzı regex alt çizgi:

/^(.?_.?_)/ 

ve üçüncü:

/^(.*?_.*?_.*?_)/ 
5

İşte bir başlangıç. Genel kullanım için bu kasa yapmak için, düzgün düzenli ifadeleri özel karakterler kaçmak için onu gerekir:

x <- c("a_b_c_d", "1_2_3_4", "<_?_._:", "", "abcd", "____abcd") 

matchToNth <- function(char, n) { 
    others <- paste0("[^", char, "]*") ## matches "[^_]*" if char is "_" 
    mainPat <- paste0(c(rep(c(others, char), n-1), others), collapse="") 
    paste0("(^", mainPat, ")", "(.*$)") 
} 

gsub(matchToNth("_", 2), "\\1", x) 
# [1] "a_b" "1_2" "<_?" ""  "abcd" "_" 

gsub(matchToNth("_", 3), "\\1", x) 
# [1] "a_b_c" "1_2_3" "<_?_." ""  "abcd" "__" 
+0

Aslında benzer bir şey üzerinde çalışıyordum. Benim yaklaşımım yakın ama seninkiyle aynı değil. Güvenli yaklaşımın iyi çağrılması, bunu qdap'de kullanıyorum; 'Kitaplığı (qdap); genX' –

+1

@TylerRinker - Sadece kabul ettiğiniz cevabın aşağıdakiler gibi dizeler için çalışmadığını unutmayın: x <- c ("_ a_b", "a__b") '. –

1

Justin'in yaklaşımını bu Benim tasarladığım neydi kullanarak bu

x 
## [1] "a_b_c_d" "1_2_3_4" "<_?_._:" 

gsub("(.*)_", "\\1", regmatches(x, regexpr("([^_]*_){1}", x))) 
## [1] "a" "1" "<" 

gsub("(.*)_", "\\1", regmatches(x, regexpr("([^_]*_){2}", x))) 
## [1] "a_b" "1_2" "<_?" 

gsub("(.*)_", "\\1", regmatches(x, regexpr("([^_]*_){3}", x))) 
## [1] "a_b_c" "1_2_3" "<_?_." 
1

gibi Belki bir şey:

beg2char <- function(text, char = " ", noc = 1, include = FALSE) { 
    inc <- ifelse(include, char, "?") 
    specchar <- c(".", "|", "(", ")", "[", "{", "^", "$", "*", "+", "?") 
    if(char %in% specchar) { 
     char <- paste0("\\", char) 
    } 
    ins <- paste(rep(paste0(char, ".+"), noc - 1), collapse="") 
    rep <- paste0("^(.+", ins, inc, ").*$") 
    gsub(rep, "\\1", text) 
} 

x <- c("a_b_c_d", "1_2_3_4", "<_?_._:") 
beg2char(x, "_", 1) 
beg2char(x, "_", 2) 
beg2char(x, "_", 3) 
beg2char(x, "_", 4) 
beg2char(x, "_", 3, include=TRUE) 
+0

Bu sonuçlar gerçekten olmasını istediğiniz şey nedir?'x <-" a____b "; beg2char (x, "_", 2); beg2char (x, "_", 1) ' –

+0

@ JoshO'Brien Sanırım öyle ama belki bir köşe davası veya bir şey görmüyorsun, özellikle ne düşünüyorsun? –

+0

Oh Yukarıdaki yorumunuzu oluşturdum. Evet, benim amacım için ama başkaları için yaklaşımın onların peşinde oldukları şey olduğunu düşünüyorum. –

İlgili konular