2013-04-25 22 views
10

Mã dưới đây hoạt động rất dài như beforeafter chuỗi không có ký tự mà đặc biệt để một regex:regex động trong R

before <- 'Name of your Manager (note "self" if you are the Manager)' #parentheses cause problem in regex 
after <- 'CURRENT FOCUS' 

pattern <- paste0(c('(?<=', before, ').*?(?=', after, ')'), collapse='') 
ex <- regmatches(x, gregexpr(pattern, x, perl=TRUE)) 

Liệu R có một chức năng để thoát khỏi chuỗi được sử dụng trong regexes?

Trả lời

5

Sử dụng \Q...\E bao vây các mẫu con nguyên văn:

# test data 
before <- "A." 
after <- ".Z" 
x <- c("A.xyz.Z", "ABxyzYZ") 

pattern <- sprintf('(?<=\\Q%s\\E).*?(?=\\Q%s\\E)', before, after) 

cung cấp:

> gregexpr(pattern, x, perl = TRUE) > 0 
[1] TRUE FALSE 
+0

thậm chí còn tốt hơn! Tôi không biết về '\ Q ... \ E'. Tôi có thể thấy nó có ích ở nhiều nơi. – dnagirl

+0

Điều này rất tiện dụng! Nếu bạn không cần 'perl = TRUE' cho regex của bạn, nó không phải là một yêu cầu cho' \ Q ... \ E' để làm việc. – severin

7

Trong Perl, có http://perldoc.perl.org/functions/quotemeta.html để thực hiện chính xác điều đó. Nếu doc ​​là đúng khi nó nói

Trả về giá trị của EXPR với tất cả các ký tự ASCII phi "từ" nhân vật backslashed. (Tức là, tất cả các ký tự ASCII không phù hợp/[A-Za-z_0-9]/sẽ được đi trước bởi một dấu chéo ngược trong chuỗi trở về, bất kể bất kỳ cài đặt locale.)

sau đó bạn có thể đạt được cùng bằng cách thực hiện:

quotemeta <- function(x) gsub("([^A-Za-z_0-9])", "\\\\\\1", x) 

Và mô hình của bạn nên là:

pattern <- paste0(c('(?<=', quotemeta(before), ').*?(?=', quotemeta(after), ')'), 
        collapse='') 

nhanh kiểm tra sự tỉnh táo:

a <- "he'l(lo)" 
grepl(a, a) 
# [1] FALSE 
grepl(quotemeta(a), a) 
# [1] TRUE 
+0

hoàn hảo! Tôi cho rằng nó không phải là một chức năng cốt lõi vì R thường không có nghĩa là để xử lý văn bản. – dnagirl

1

dnagirl, một chức năng như vậy tồn tại và là glob2rx

a <- "he'l(lo)" 
tt <- glob2rx(a) 
# [1] "^he'l\\(lo)$" 

before <- 'Name of your Manager (note "self" if you are the Manager)' 
tt <- glob2rx(before) 
# [1] "^Name of your Manager \\(note \"self\" if you are the Manager)$" 

Bạn chỉ có thể loại bỏ các "^" và "$" từ chuỗi bằng cách thực hiện:

substr(tt, 2, nchar(tt)-1) 
# [1] "he'l\\(lo)" 
+0

Tôi đã thấy 'glob2rx' trước khi tôi đăng câu trả lời của mình. Tôi không nghĩ rằng đó là chức năng cho nhiệm vụ, hãy thử những thứ như 'glob2rx (". * ")' Chẳng hạn. – flodel

+0

@flodel, tôi biết về những hạn chế của nó. Hầu hết thời gian nó làm việc cho tôi. Lý do duy nhất tôi đăng ở đây là vì [** bài đăng này của Ricardo **] (http://stackoverflow.com/questions/16224620/r-strings-to-regex-appropriate-strings#16224620) có vẻ như câu hỏi là bản sao chính xác của câu hỏi này .. và tôi được yêu cầu đăng nhận xét của tôi ở đây dưới dạng câu trả lời. – Arun

Các vấn đề liên quan