趣旨
パッケージを作成したり他人とコードを共有する場合、コードの日本語をエスケープさせるほうが良いことが多いです。そこで、自作関数などに含まれる日本語を簡単にエスケープさせる方法を編み出したのでTipsとして記しておきます。
使うパッケージ
- stringi (必須)
- stringr (必須)
- clipr (推奨)
library(stringi); library(stringr); library(clipr)
流れ
① 関数を読み込む ⇒ ② 変換後の内容をクリップボードに保存 ⇒ ③ スクリプトやメモ帳に貼り付け
今回変換したい関数
適当な法隆寺関数を用意しました。
この関数に含まれる日本語を手作業ではなくRを使って何とかエスケープさせましょう。
今回のターゲット
f1 <- function(){
print("正岡子規") # 小峠ではない
fx <- function(){cat("有名な\nやーつ\n")}
fx()
"a" %>%
print()
print(paste("柿食へば",
"鐘が鳴るなり",
"法隆寺"))
# いい俳句だ
}
関数の実行結果
> f1()
[1] "正岡子規"
有名な
やーつ
[1] "a"
[1] "柿食へば 鐘が鳴るなり 法隆寺"
やってみよう
コードを実行すると、クリップボードに置換後の関数が自動で記録されます。
2020/03/09 追記: 大幅変更
コメントアウトは置換しない場合
f1 %>%
getSrcref %>%
as.character %>%
stringi::stri_escape_unicode() -> tx
while(sum(str_detect(tx, pattern = "#.*\\\\u")) > 0) {
tx <- stringi::stri_replace_all_regex(tx, pattern = "#(.*)\\\\u", replacement = "#$1\\\\_u")} %>%
stringr::str_replace_all(pattern = "^.*\\\\u", replacement = "\\\\\\\\u") %>%
stringr::str_replace_all(., "\\\\_u", "\\\\u") %>%
stringi::stri_unescape_unicode() %>%
clipr::write_clip()
置換後のクリップボードの内容
function(){
print("\u6b63\u5ca1\u5b50\u898f") # 小峠ではない
fx <- function(){cat("\u6709\u540d\u306a\n\u3084\u30fc\u3064\n")}
fx()
"a" %>%
print()
print(paste("\u67ff\u98df\u3078\u3070",
"\u9418\u304c\u9cf4\u308b\u306a\u308a",
"\u6cd5\u9686\u5bfa"))
# いい俳句だ
}
置換後の関数の実行結果
> f2 <- function(){
print("\u6b63\u5ca1\u5b50\u898f") # 小峠ではない
fx <- function(){cat("\u6709\u540d\u306a\n\u3084\u30fc\u3064\n")}
fx()
"a" %>%
print()
print(paste("\u67ff\u98df\u3078\u3070",
"\u9418\u304c\u9cf4\u308b\u306a\u308a",
"\u6cd5\u9686\u5bfa"))
# いい俳句だ
}
> f2()
[1] "正岡子規"
有名な
やーつ
[1] "a"
[1] "柿食へば 鐘が鳴るなり 法隆寺"
コメントアウトも置換する場合
f1 %>%
getSrcref %>%
as.character %>%
stringi::stri_escape_unicode() %>%
stringr::str_replace_all(pattern = "\\\\u", replacement = "\\\\\\\\u") %>%
stringi::stri_unescape_unicode() %>%
clipr::write_clip()
置換後のクリップボードの内容
function(){
print("\u6b63\u5ca1\u5b50\u898f") # \u5c0f\u5ce0\u3067\u306f\u306a\u3044
fx <- function(){cat("\u6709\u540d\u306a\n\u3084\u30fc\u3064\n")}
fx()
"a" %>%
print()
print(paste("\u67ff\u98df\u3078\u3070",
"\u9418\u304c\u9cf4\u308b\u306a\u308a",
"\u6cd5\u9686\u5bfa"))
# \u3044\u3044\u4ff3\u53e5\u3060
}
注意点
遵守すべきこと
- data.frameの各列やリストの各要素にアクセスする際、「
$
」の使用は避けてください。これは、$日本語の文字列
とするとエスケープした文字列をRが上手く処理できないためです。つまり、日本語の文字列が必ず""
で囲う形になるようにコードを修正します。以下の例を参考にしてください。
# Example Data
> lst <- list("い" = 1, "ろ" = 2)
> df <- data.frame("は" = 1, "に" = 2)
# このような記述は避ける
> lst$い
[1] 1
> df$は
[1] 1
# このように書き換える
> lst[["い"]]
[1] 1
> df[["は"]]
[1] 1
そうでもない問題(解消)
実行結果には全く影響はないですが、もし必要であれば一部手直しが必要です。
置換後はコメント#
は消えてしまいます。引数内の改行・パイプ演算子毎の改行も消えてしまいます。
詳しくは上の例を参考にしてください。
2020/03/09 追記: この問題を解決しました。
【R】 関数のコードを文字列として取得する - Qiita
おわりに
いちいち変換してらんないので、めっちゃ楽になりました(自画自賛)
お試しあれ。
Enjoy!
おしまい。