96

Rでは、正規表現の一致からグループキャプチャを抽出することは可能ですか?私の知る限り、、、、、、、、またはグループキャプチャを返すgrepものはgreplありません。regexprgregexprsubgsub

このようにエンコードされた文字列からキーと値のペアを抽出する必要があります。

\((.*?) :: (0\.[0-9]+)\)

私はいつでも複数の完全一致のgrepsを実行することも、外部(非R)処理を実行することもできますが、すべてR内で実行できることを望んでいました。これを実行する関数またはそのような関数を提供するパッケージはありますか?

4

9 に答える 9

124

str_match()stringrパッケージから、これを行います。一致するグループごとに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"    
于 2012-04-06T03:13:48.140 に答える
59

あなたの例から、gsubはこれを行います:

gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"

引用符内の\sを二重にエスケープする必要があります。そうすると、正規表現で機能します。

お役に立てれば。

于 2009-06-04T22:44:29.217 に答える
40

試してみてregmatches()くださいregexec()

regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)"))
[[1]]
[1] "(sometext :: 0.1231313213)" "sometext"                   "0.1231313213"
于 2013-05-15T11:32:09.357 に答える
20

gsub()はこれを実行し、キャプチャグループのみを返すことができます。

ただし、これを機能させるには、gsub()ヘルプに記載されているように、キャプチャグループ外の要素を明示的に選択する必要があります。

(...)置換されていない文字ベクトル'x'の要素は変更されずに返されます。

したがって、選択するテキストが文字列の途中にある場合は、キャプチャグループの前後に。*を追加すると、そのテキストのみを返すことができます。

gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)") [1] "sometext 0.1231313213"

于 2011-04-26T21:43:05.503 に答える
4

私は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
}
于 2015-01-29T16:53:12.313 に答える
4

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
于 2017-08-24T01:22:29.637 に答える
3

これが私がこの問題を回避することになった方法です。2つの別々の正規表現を使用して1番目と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"))
于 2009-06-05T16:06:42.463 に答える
2

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"
于 2015-12-23T15:37:15.650 に答える
1

これは、パッケージunglueを使用して、選択した回答の例を使用して実行できます。

# install.packages("unglue")
library(unglue)

s <- c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
unglue_data(s, "({x} :: {y})")
#>          x            y
#> 1 sometext 0.1231313213
#> 2 moretext     0.111222

またはデータフレームから開始

df <- data.frame(col = s)
unglue_unnest(df, col, "({x} :: {y})",remove = FALSE)
#>                          col        x            y
#> 1 (sometext :: 0.1231313213) sometext 0.1231313213
#> 2     (moretext :: 0.111222) moretext     0.111222

unglueパターンから、オプションで名前付きキャプチャを使用して、生の正規表現を取得できます。

unglue_regex("({x} :: {y})")
#>             ({x} :: {y}) 
#> "^\\((.*?) :: (.*?)\\)$"

unglue_regex("({x} :: {y})",named_capture = TRUE)
#>                     ({x} :: {y}) 
#> "^\\((?<x>.*?) :: (?<y>.*?)\\)$"

詳細:https ://github.com/moodymudskipper/unglue/blob/master/README.md

于 2019-11-06T12:04:51.447 に答える