7

私は本当に正規表現の学習に時間を費やしており、さまざまなおもちゃのシナリオで遊んでいます。私が作業できないセットアップの 1 つは、文字列の先頭からn > 1の文字の n 個の出現までを取得することです。

ここでは、文字列の先頭から最初のアンダースコアまでを取得できますが、これを 2 番目または 3 番目のアンダースコアに一般化することはできません。

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" "<_?_."

関連記事:最初の文字から文字列の最後までの正規表現

4

5 に答える 5

5

ここから始めます。これを一般的な使用で安全にするには、正規表現の特殊文字を適切にエスケープする必要があります。

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"  "__"   
于 2013-04-09T18:48:37.410 に答える
3

どうですか:

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

{}または、繰り返し回数を示すために使用できます...

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

したがって、n番目のものと一致させたい場合は、自分自身を繰り返す必要はありません...

于 2013-04-09T18:31:09.590 に答える
1

たぶん、このようなもの

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" "<_?_."
于 2013-04-09T18:52:00.983 に答える