Автоматически экранировать символы Юникода

Как вы можете отобразить строку в юникоде, скажем:

x <- "•"

используя его экранированный эквивалент?

y <- "\u2022"

identical(x, y)
# [1] TRUE

(Я хотел бы иметь возможность сделать это, потому что пакеты CRAN должны содержать только ASCII, но иногда вы хотите использовать Unicode в сообщении об ошибке или аналогичном)

r
12 голосов | спросил hadley 14 PM00000050000005131 2014, 17:12:51

3 ответа


0

После изучения некоторой документации по iconv я думаю, что вы можете сделать это, используя только base. Но вам нужно уделить дополнительное внимание кодированию строки.

В системе с кодировкой UTF-8:

> stri_escape_unicode("你好世界")
[1] "\\u4f60\\u597d\\u4e16\\u754c"

# use big endian
> iconv(x, "UTF-8", "UTF-16BE", toRaw=T)
[[1]]
[1] 4f 60 59 7d 4e 16 75 4c

> x <- "•"
> iconv(x, "UTF-8", "UTF-16BE", toRaw=T)    
[[1]]
[1] 20 22

Но если вы работаете в системе с кодировкой latin1, все может пойти не так.

> x <- "•"
> y <- "\u2022"
> identical(x, y)
[1] FALSE
> stri_escape_unicode(x)
[1] "\\u0095" # <- oops!

# culprit
> Encoding(x)
[1] "latin1"

# and it causes problem for iconv
> iconv(x, Encoding(x), "Unicode")
Error in iconv(x, Encoding(x), "Unicode") : 
  unsupported conversion from 'latin1' to 'Unicode' in codepage 1252
> iconv(x, Encoding(x), "UTF-16BE")
Error in iconv(x, Encoding(x), "UTF-16BE") : 
  embedded nul in string: '\0•'

Перед преобразованием в Unicode безопаснее привести строку в UTF-8:

> iconv(enc2utf8(enc2native(x)), "UTF-8", "UTF-16BE", toRaw=T)
[[1]]
[1] 20 22

РЕДАКТИРОВАТЬ: это может вызвать некоторые проблемы для строк уже в кодировке UTF-8 в некоторых конкретных системах. Может быть, безопаснее проверить кодировку перед преобразованием.

> Encoding("•")
[1] "latin1"
> enc2native("•")
[1] "•"
> enc2native("\u2022")
[1] "•"
# on a Windows with default latin1 encoding
> Encoding("测试") 
[1] "UTF-8"
> enc2native("测试") 
[1] "<U+6D4B><U+8BD5>"   # <- BAD! 

Для некоторых символов или языков UTF-16 может быть недостаточно. Поэтому, вероятно, вам следует использовать UTF-32, так как

  

Форма символа UTF-32 является прямым представлением его кодовой точки.

Исходя из описанных выше методов проб и ошибок, ниже приведена, вероятно, одна более безопасная escape-функция, которую мы можем написать:

unicode_escape <- function(x, endian="big") {
  if (Encoding(x) != 'UTF-8') {
    x <- enc2utf8(enc2native(x))
  }
  to.enc <- ifelse(endian == 'big', 'UTF-32BE', 'UTF-32LE')

  bytes <- strtoi(unlist(iconv(x, "UTF-8", "UTF-32BE", toRaw=T)), base=16)
  # there may be some better way to do thibs.
  runes <- matrix(bytes, nrow=4)
  escaped <- apply(runes, 2, function(rb) {
    nonzero.bytes <- rb[rb > 0]
    ifelse(length(nonzero.bytes) > 1, 
           # convert back to hex
           paste("\\u", paste(as.hexmode(nonzero.bytes), collapse=""), sep=""),
           rawToChar(as.raw(nonzero.bytes))
           )
  })
  paste(escaped, collapse="")
}

Тесты:

> unicode_escape("•••ERROR!!!•••")
[1] "\\u2022\\u2022\\u2022ERROR!!!\\u2022\\u2022\\u2022"
> unicode_escape("Hello word! 你好世界!")
[1] "Hello word! \\u4f60\\u597d\\u4e16\\u754c!"
> "\u4f60\u597d\u4e16\u754c"
[1] "你好世界"
ответил Xin Yin 14 PM00000060000004831 2014, 18:17:48
0

В пакете stringi есть метод для этого

stri_escape_unicode(y)
# [1] "\\u2022"
ответил konvas 14 PM00000050000000531 2014, 17:36:05
0

Я написал небольшой пакет с именем uniscape, который может преобразовывать не-ASCII-символы в соответствующий "\u1234" или "\U12345678" escape-коды Unicode (очевидно, с обратной косой чертой). Это может быть сделано для любого символа или только для символов внутри строки R (одинарные или двойные кавычки). В следующем примере показано, как u_escape преобразует символ. Выходные данные затем заключаются в кавычки, анализируются и оцениваются. Окончательный результат соответствует исходному символу.

x <- rawToChar(as.raw(c(0xe2, 0x80, 0xa2)))
Encoding(x) <- "UTF-8"
x
# [1] "•"
x_u <- uniscape::u_escape(x)
x_u
# [1] "\\u2022"
y <- eval(parse(text = paste0('"', x_u, '"')))
y
# [1] "•"
identical(x, y)
# [1] TRUE

Пакет (на GitHub ) также предоставляет надстройки RStudio для удобства. Надстройки работают с активным исходным редактором документа. Пакет не имеет жестких зависимостей, кроме rstudioapi.

На этом рисунке показан пример документа с выделенной текстовой областью и окном надстройки RStudio с тремя надстройками uniscape. «Escape selection» было выбрано. Пример документа и окна добавления

Это результат после применения «Escape selection», с автоматически выбранной последовательностью кодирования каждого не ASCII символа . Результат добавления выделения Escape

После отмены предыдущей операции это результат для "Escape-строки в файле". Каждая затронутая строка R в активном файле автоматически подсвечивается надстройкой. Закомментированные строки игнорируются. «Escape selected strings» делает то же самое, но только для выбранной текстовой области. Результат Escape-строк в файле

ответил mvkorpel 8 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 08 Sep 2018 09:17:41 +0300 2018, 09:17:41

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132