Rでは、正規表現の一致からグループキャプチャを抽出できますか?私が知る限り、grep
、grepl
、regexpr
、gregexpr
、sub
、またはgsub
のいずれもグループキャプチャを返しません。
このようにエンコードされた文字列からキーと値のペアを抽出する必要があります。
\((.*?) :: (0\.[0-9]+)\)
常に複数の完全一致grepsを実行することも、外部(R以外)の処理を実行することもできますが、R内ですべて実行できることを望んでいました。これを行うための関数またはパッケージがありますか?
stringr
パッケージのstr_match()
はこれを行います。マッチ内のグループごとに1列(およびマッチ全体に1列)の文字マトリックスを返します。
> s = c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
> str_match(s, "\\((.*?) :: (0\\.[0-9]+)\\)")
[,1] [,2] [,3]
[1,] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
[2,] "(moretext :: 0.111222)" "moretext" "0.111222"
あなたの例から、gsubはこれを行います:
gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"
引用符で\ sを二重エスケープする必要があり、正規表現で機能します。
お役に立てれば。
regmatches()
とregexec()
を試してください:
regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)"))
[[1]]
[1] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
gsub()はこれを行うことができ、キャプチャグループのみを返します。
ただし、これが機能するためには、gsub()ヘルプで説明されているように、キャプチャグループ外の要素を明示的に選択する必要があります。
(...)置換されない文字ベクトル 'x'の要素は、変更されずに返されます。
そのため、選択するテキストが文字列の途中にある場合、キャプチャグループの前後に。*を追加すると、それだけを返すことができます。
gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"
Perl互換の正規表現が好きです。おそらく誰か他の人も...
Perl互換の正規表現を実行し、私が慣れている他の言語の関数の機能と一致する関数を次に示します。
regexpr_Perl <- function(expr, str) {
match <- regexpr(expr, str, Perl=T)
matches <- character(0)
if (attr(match, 'match.length') >= 0) {
capture_start <- attr(match, 'capture.start')
capture_length <- attr(match, 'capture.length')
total_matches <- 1 + length(capture_start)
matches <- character(total_matches)
matches[1] <- substr(str, match, match + attr(match, 'match.length') - 1)
if (length(capture_start) > 1) {
for (i in 1:length(capture_start)) {
matches[i + 1] <- substr(str, capture_start[[i]], capture_start[[i]] + capture_length[[i]] - 1)
}
}
}
matches
}
これが、この問題を回避する方法です。 2つの別個の正規表現を使用して、最初と2番目のキャプチャグループを一致させ、2つのgregexpr
呼び出しを実行してから、一致した部分文字列を引き出します。
regex.string <- "(?<=\\().*?(?= :: )"
regex.number <- "(?<= :: )\\d\\.\\d+"
match.string <- gregexpr(regex.string, str, Perl=T)[[1]]
match.number <- gregexpr(regex.number, str, Perl=T)[[1]]
strings <- mapply(function (start, len) substr(str, start, start+len-1),
match.string,
attr(match.string, "match.length"))
numbers <- mapply(function (start, len) as.numeric(substr(str, start, start+len-1)),
match.number,
attr(match.number, "match.length"))
stringr
パッケージで提案されているように、これはstr_match()
またはstr_extract()
を使用して実現できます。
マニュアルから改編:
library(stringr)
strings <- c(" 219 733 8965", "329-293-8753 ", "banana",
"239 923 8115 and 842 566 4692",
"Work: 579-499-7527", "$1000",
"Home: 543.355.3679")
phone <- "([2-9][0-9]{2})[- .]([0-9]{3})[- .]([0-9]{4})"
グループの抽出と結合:
str_extract_all(strings, phone, simplify=T)
# [,1] [,2]
# [1,] "219 733 8965" ""
# [2,] "329-293-8753" ""
# [3,] "" ""
# [4,] "239 923 8115" "842 566 4692"
# [5,] "579-499-7527" ""
# [6,] "" ""
# [7,] "543.355.3679" ""
出力行列でグループを示す(列2+に興味があります):
str_match_all(strings, phone)
# [[1]]
# [,1] [,2] [,3] [,4]
# [1,] "219 733 8965" "219" "733" "8965"
#
# [[2]]
# [,1] [,2] [,3] [,4]
# [1,] "329-293-8753" "329" "293" "8753"
#
# [[3]]
# [,1] [,2] [,3] [,4]
#
# [[4]]
# [,1] [,2] [,3] [,4]
# [1,] "239 923 8115" "239" "923" "8115"
# [2,] "842 566 4692" "842" "566" "4692"
#
# [[5]]
# [,1] [,2] [,3] [,4]
# [1,] "579-499-7527" "579" "499" "7527"
#
# [[6]]
# [,1] [,2] [,3] [,4]
#
# [[7]]
# [,1] [,2] [,3] [,4]
# [1,] "543.355.3679" "543" "355" "3679"
strcapture
からのutils
を使用したソリューション:
x <- c("key1 :: 0.01",
"key2 :: 0.02")
strcapture(pattern = "(.*) :: (0\\.[0-9]+)",
x = x,
proto = list(key = character(), value = double()))
#> key value
#> 1 key1 0.01
#> 2 key2 0.02