26

検索する文字列の代わりに正規表現を作成したいので、検索した文字列に正規表現文字が含まれている場合でも機能するように、これらの文字列をエスケープしてから正規表現に入れる必要があります。

一部の言語には、これを行う関数があります(例:python re.escapehttps ://stackoverflow.com/a/10013356/1900520 )。Rにはそのような機能がありますか?

例(構成された関数):

x = "foo[bar]"
y = escape(x) # y should now be "foo\\[bar\\]"
4

5 に答える 5

24

私はPerlのquotemeta関数のRバージョンを書きました:

library(stringr)
quotemeta <- function(string) {
  str_replace_all(string, "(\\W)", "\\\\\\1")
}

私はいつも正規表現のperlフレーバーを使用しているので、これは私にとってはうまくいきます。Rの「通常の」正規表現で機能するかどうかはわかりません。

編集:これが機能する理由を説明するソースを見つけました。これは、 perlreのマンページの「QuotingMetacharacters」セクションにあります

これはかつて、パターンに使用する文字列内の正規表現メタ文字の特別な意味を無効化または引用するために、一般的なイディオムで使用されていました。「単語」以外のすべての文字を引用するだけです。

$pattern =~ s/(\W)/\\$1/g;

ご覧のとおり、上記のRコードは、これと同じ置換を直接変換したものです(バックスラッシュ地獄を通過した後)。マンページにも(私の強調)と書かれています:

他のいくつかの正規表現言語とは異なり、英数字でないバックスラッシュ記号はありません。

これは、このソリューションがPCREに対してのみ保証されているという私の主張を裏付けるものです。

于 2013-02-12T17:57:57.417 に答える
14

どうやらescapeRegexHmiscパッケージで呼び出される関数があります。関数自体には、「文字列」の入力値に対して次の定義があります。

gsub("([.|()\\^{}+$*?]|\\[|\\])", "\\\\\\1", string)

私の以前の答え:

組み込み関数があるかどうかはわかりませんが、自分のやりたいことを実行できるようにすることができます。これは基本的に、置換したい値のベクトルとそれらを置換したいもののベクトルを作成し、必要な置換を行う値をループします。

re.escape <- function(strings){
    vals <- c("\\\\", "\\[", "\\]", "\\(", "\\)", 
              "\\{", "\\}", "\\^", "\\$","\\*", 
              "\\+", "\\?", "\\.", "\\|")
    replace.vals <- paste0("\\\\", vals)
    for(i in seq_along(vals)){
        strings <- gsub(vals[i], replace.vals[i], strings)
    }
    strings
}

一部の出力

> test.strings <- c("What the $^&(){}.*|?", "foo[bar]")
> re.escape(test.strings)
[1] "What the \\$\\^&\\(\\)\\{\\}\\.\\*\\|\\?"
[2] "foo\\[bar\\]"  
于 2013-02-12T17:31:44.917 に答える
4

@ryanthompson関数よりも簡単な方法は、文字列の前に追加し\\Qて後置することです。\\Eヘルプファイルを参照してください?base::regex

于 2019-04-23T11:48:08.940 に答える
1

レックスパッケージを使用する

最近では、すべての正規表現を。を使用して記述していrexます。あなたの特定の例のために、rexあなたが望むことを正確に行います:

library(rex)
library(assertthat)
x = "foo[bar]"
y = rex(x)
assert_that(y == "foo\\[bar\\]")

しかしもちろん、rexそれ以上のことをします。質問は正規表現の構築に言及しており、それがまさにそのrexために設計されたものです。たとえば、の正確な文字列をx、前後に何も含めずに一致させたいとします。

x = "foo[bar]"
y = rex(start, x, end)

これで、 yは^foo\[bar\]$xに含まれる正確な文字列とのみ一致します。

于 2021-05-06T05:24:27.100 に答える
0

によると?regex

記号\wは「単語」文字([[:alnum:]_]、拡張子の同義語)と一致し、\Wその否定([^[:alnum:]_])です。

したがって、キャプチャグループを使用して、(\\W)単語以外の文字の出現を検出し、\\1-syntaxでエスケープできます。

> gsub("(\\W)", "\\\\\\1", "[](){}.|^+$*?\\These are words")
[1] "\\[\\]\\(\\)\\{\\}\\.\\|\\^\\+\\$\\*\\?\\\\These\\ are\\ words"

または同様に、を置き換え"([^[:alnum:]_])"ます "(\\W)"

于 2022-02-10T13:32:34.263 に答える