stri_unescape_unicode() не работает с некоторыми символами

У меня проблема с преобразованием символов Юникода в R. Я следую этому подходу, но stri_unescape_unicode из библиотеки stringi не возвращает правильный значение в некоторых случаях. Позвольте мне показать пример, где правильным значением должно быть слово Tomáš:

library(stringi)
test <- "Tom<U+00E1><U+009A>"
test <- gsub("<U\\+(....)>", "\\\\u\\1", test)
stri_unescape_unicode(test)
[1] "Tomá\u009a"

Однако, если š представлен U+ 0161 вместо U+009A, все работает как положено:

test2 <- "Tom<U+00E1><U+0161>"
test2 <- gsub("<U\\+(....)>", "\\\\u\\1", test2)
stri_unescape_unicode(test2)
[1] "Tomáš"

Теперь моя проблема в том, что у меня есть большой вектор character с многочисленными элементами, такими как test и stri_unescape_unicode, которые не работают с некоторыми персонажами, такими как <U+009A> здесь. Мой вопрос:

  • Есть ли способ преобразовать <U+009A> с помощью stri_unescape_unicode или любого другого метода?
  • В качестве альтернативы, есть ли способ автоматически заменить юникоды в случае сбоя stri_unescape_unicode? То есть в моем примере "Tom<U+00E1><U+009A>" должно стать "Tom<U+00E1><U+0161>"?

person pieca    schedule 07.06.2018    source источник


Ответы (1)


Похоже, что stri_unescape_unicode() не потерпел неудачу. Символ был преобразован, но он является управляющим символом («ввод одиночного символа» U+009A) и печатается с использованием его кода. Мусор на входе, мусор на выходе.

То, как R печатает строки Unicode, зависит от типа консоли и используемой локали. Следующий пример был запущен через пакет reprex с кодовой страницей 1252 в Windows. Несмотря на то, что непечатаемый символ печатается с использованием стиля <U+> или \u, фактический символ Unicode существует в соответствующей строке R.

library(stringi)
test2 <- c("Tom<U+00E1><U+009A>", "Tom<U+00E1><U+0161>")
test2 <- gsub("<U\\+(....)>", "\\\\u\\1", test2)
unesc2 <- stri_unescape_unicode(test2)
unesc2
#> [1] "Tomá<U+009A>" "Tomáš"
nchar(unesc2)
#> [1] 5 5
cap2 <- capture.output(cat(unesc2, sep = "\n"))
cap2
#> [1] "Tomá<U+009A>" "Tomáš"
nchar(cap2)
#> [1] 12  5
which(nchar(cap2) > nchar(unesc2))
#> [1] 1
es2 <- encodeString(unesc2)
es2
#> [1] "Tomá\\u009a" "Tomáš"
nchar(es2)
#> [1] 10  5
which(nchar(es2) > nchar(unesc2))
#> [1] 1

Я думаю, что capture.output() или encodeString() в сочетании с nchar() можно использовать, как указано выше, для обнаружения строк с плохими, то есть непечатаемыми в текущей локали, символами. Затем, если кажется, что все случаи U+009A на самом деле должны быть U+0161, их исправление — простая работа для gsub(), например, gsub("\u009a", "\u0161", unesc2) и так далее.

person mvkorpel    schedule 20.12.2018
comment
Да, «ручная» замена этих символов — это то, чем я тогда занимался. Спасибо за ответы! - person pieca; 20.12.2018