少し気になったら深みにはまってしまった。Rで絵文字の正規表現を実行する方法について調べてみたので整理してみる。

🉑 マッチするパターン

grep(pattern = "\xF0\x9F\x98\x81", "😁")
## [1] 1
grep(pattern = "\U0001f601", x = "絵文字だよ 😁", value = TRUE)
## [1] "絵文字だよ \U0001f601"

途中の0は省略しても良い 🙆

grepl(pattern = "\U1f601", x = "絵文字だよ 😁")
## [1] TRUE

enc2utf8()関数でバイト表記からUnicodeに変換することもできる。

enc2utf8("\xF0\x9F\x98\x81")
## [1] "\U0001f601"
grepl(enc2utf8("\xF0\x9F\x98\x81"), "絵文字だよ 😁")
## [1] TRUE
grep(enc2utf8("\xF0\x9F\x98\x81"), "😁", value = TRUE)
## [1] "\U0001f601"

ではすべての絵文字を網羅するための文字集合はどう指定すれば良いか ❓

grepl("[\U0001F600-\U0001F64F]", c("😁", "🐳", "😄"))
## [1]  TRUE FALSE  TRUE

上記の例では顔文字は該当するが鯨の絵文字はマッチしていないので不十分 🙅。iPhoneやGitHubを始めとした各種ウェブサービスで使われる(普及している絵文字を含んだ)Unicode 6.0をカバーするには次のような正規表現で抽出する。

# v6.0
grepl("[\U0001F0CF-\U000207BF]", c("😁", "🐳", "😄"))
## [1] TRUE TRUE TRUE

Unicode 6.0以降に登録された絵文字についても、各バージョンのUnicodeをもとに同様にマッチングできる。以前に http://rpubs.com/uri-sy/emoji_table でUnicodeのバージョンを絵文字のリストを作成したものがあるので、それを参考にしてそれぞれのバージョンで最小値と最大値を指定すれば良い 🙆

# v7.0
grepl("[\U0001F321-\U000203FA]", c("🛳", "🏌", "🌡"))
## [1] TRUE TRUE TRUE
# v8.0
grepl("[\U0001F32D-\U0001F9C0]", c("🤖", "🌭", "🦄"))
## [1] TRUE TRUE TRUE

というわけで現在登録されているすべての絵文字にマッチする文字集合はこのようになる。(多分きちんとできているはず)

grepl("[\U0001F0CF-\U0001F9C0]", c("🛳", "😁", "🐳", "🦄"))
## [1] TRUE TRUE TRUE TRUE

また、絵文字にはより簡易な記号やグリフやらも含まれるのでそれらもマッチに含めるとこのようになる…はず。

remoji::emoji(list_emoji(), TRUE) %>% min()
## [1] "〰️ "
# 結果は省略。
#   すべてTRUEにならないのは同じ絵文字でも複数のunicodeが指定されているものがあるためか
grepl("[\U000270A-\U0001F9C0]", remoji::emoji(list_emoji(), TRUE))

as.hexmode()関数を使ってas.numeric()で数値化するパターン。

as.hexmode("0001F1FC") %>% {
  print(.)
  as.numeric(.)
}
## [1] "1f1fc"
## [1] 127484

絵文字の挙動は面白い。

# print()では絵文字を出力することはできない
print("😁")
## [1] "\U0001f601"
# message()とcat()関数はコンソール上に絵文字を「絵文字」として出力する
cat("😁")
## 😁
message("😁")

x <- "\xF0\x9F\x98\x81"
cat(x)
## 😁
enc2utf8("\U001F32D") %>% cat()
## 🌭

enjoy 😊