2017-08-15 6 views
0

私はこのように見える文字列のベクトルを持っている:R:正規表現の狂気(stringi)

G30(H).G3(M).G0(L).Replicate(1) 

反復処理c("H", "M", "L")以上、私はG3M "のために、(「H" のため)G30を抽出したいと思います")とG0(" L "の場合)。

私はさまざまな試みを私に混乱させています。 - regex101.comデバッガ... (\w*)\(M\)がうまく機能することを示しますが、Rは失敗に...

+0

regex101.comの試行[こちら](https:// regex101)をご覧ください。com/r/cZ0sD2/66)。 – balin

+0

あなたは多くの回答をいただきました!最も有用で最も一般的なものを見つけたもの(回答の左側のチェックマーク)を受け入れることを検討してください。それはコミュニティがあなたのために働いた答えを知り、あなたが受け取った助けを認めます。 – CPak

答えて

2

:これは最初の過去のターゲット文字のすべてのインスタンスを無視

library(stringi) 

strings <- c(
    "G30(H).G3(M).G0(L).Replicate(1)", 
    "G5(M).G11(L).G6(H).Replicate(9)", 
    "G10(M).G6(H).G8(M).Replicate(200)" # No "L", repeated "M" 
) 
targets <- c("H", "M", "L") 
patterns <- paste0("\\w+(?=\\(", targets, "\\))") 
matches <- outer(strings, patterns, FUN = stri_extract_first_regex) 
colnames(matches) <- targets 
matches 
#  H  M L  
# [1,] "G30" "G3" "G0" 
# [2,] "G6" "G5" "G11" 
# [3,] "G6" "G10" NA 

、あなたにNAときに、ターゲットのを与えます見つからず、すべてを単純な行列で返します。 patternsに格納されている正規表現は、XX(Y)のような部分文字列に一致します。Yはターゲット文字、XXは任意の数の単語文字です。

+0

Whoa - 私はここで何か新しいことを学びました! 'アウター'の使用は素晴らしいです! – balin

1

が、私はよりよい解決策があるかなり確信していることを転送するが、これは動作します

jnk <- 'G30(H).G3(M).G0(L).Replicate(1)' 
patter <- '([^\\(]+)\\(H\\)\\.([^\\(]+)\\(M\\)\\.([^\\(]+)\\(L\\)\\.Replicate\\(\\d+\\)' 
H <- sub(patter, '\\1', jnk) 
M <- sub(patter, '\\2', jnk) 
L <- sub(patter, '\\3', jnk) 

EDIT:

実際に、私は一度非常に良い機能を発見しましたparse.oneこれは、正規表現のようなPythonでさらに検索することができます...

これを見てください:

parse.one <- function(res, result) { 
    m <- do.call(rbind, lapply(seq_along(res), function(i) { 
    if(result[i] == -1) return("") 
    st <- attr(result, "capture.start")[i, ] 
    substring(res[i], st, st + attr(result, "capture.length")[i, ] - 1) 
    })) 
    colnames(m) <- attr(result, "capture.names") 
    m 
} 
jnk <- 'G30(H).G3(M).G0(L).Replicate(1)' 
pattern <- '(?<H>[^\\(]+)\\(H\\)\\.(?<M>[^\\(]+)\\(M\\)\\.(?<L>[^\\(]+)\\(L\\)\\.Replicate\\(\\d+\\)' 
parse.one(jnk, regexpr(pattern, jnk, perl=TRUE)) 

結果は次のようになります。順序は常に同じである場合

> parse.one(jnk, regexpr(pattern, jnk, perl=TRUE)) 
    H  M L 
[1,] "G30" "G3" "G0" 
1

、代替文字列を分割するかもしれません。例えば:

string <- "G30(H).G3(M).G0(L).Replicate(1)" 
tmp <- str_split(string, "\\.")[[1]] 
lapply(tmp[1:3], function(x) str_split(x, "\\(")[[1]][1]) 
[[1]] 
[1] "G30" 

[[2]] 
[1] "G3" 

[[3]] 
[1] "G0" 
1

コード(例えば、「G30」)タグの前(例えば、「(H)。」)または文字列のタグの順序は、(異なる文字または長さを変更することが許可されている場合)、regexpr()に基づいて、より柔軟なソリューションを試してみてください。

aa <-paste("G30(H).G3(M).G0(L).Replicate(",1:10,")", sep="") 
my.tags <- c("H","M", "L") 

extr.data <- lapply(my.tags, (function(tag){ 
    pat <- paste("\\(", tag, "\\)\\.", sep="") 
    pos <- regexpr(paste("(^|\\.)([[:alnum:]])*", pat ,sep=""), aa) 
    out <- substr(aa, pos, (pos+attributes(pos)$match.length - 4 - length(tag))) 
    gsub("(^\\.)", "", out) 
})) 
names(extr.data) <- my.tags 
extr.data 
1

私は関数(G ...)は可変で入力は可変であると仮定します。これはあなたの関数がGで始まり、あなたの入力は常に文字であることを前提としています。

parse = function(arb){ 
    tmp = stringi::stri_extract_all_regex(arb,"G.*?\\([A-Z]\\)")[[1]] 
    unlist(lapply(lapply(tmp,strsplit,"\\)|\\("),function(x){ 
    output = x[[1]][1] 
    names(output) = x[[1]][2] 
    return(output) 
    })) 
} 

これは最初にすべてのG関数を入力で解析します。次に、それらのそれぞれは、それらの機能部分とその入力部分に分割される。これは、入力のために名前を付けられた関数の文字ベクトルに入れられます。 stringiパッケージとouter()機能を使用して

parse("G30(H).G3(M).G0(L).Replicate(1)") 
>  H  M  L 
    "G30" "G3" "G0" 

それとも

parse("G35(L).G31(P).G02(K).Replicate(1)") 
>  L  P  K 
    "G35" "G31" "G02"