R中paste0生成带反斜杠的输入传入iconv()无法生效问题
问题核心
paste0拼接生成的\\xf0类内容是字面量组合字符,和代码里直接书写的"\xf0"本质完全不同:
- 代码中直接写
"\xf0"时,R在代码解析阶段就会将\xNN格式的转义序列转换为对应值的单个原始字节,也就是0xf0 - 运行时通过
paste0拼接得到的字符串,是反斜杠、x、十六进制字符组成的多个独立普通字符,R不会对运行时生成的字符串二次执行转义解析,因此iconv接收到的根本不是目标EBCDIC编码字节,自然转码异常。
cat()输出看起来和转义写法一致,只是因为它直接打印了字符串内的字面反斜杠和x字符,并非真的将内容解析为了转义字节。使用原始字符串拼接结果一致,也是因为最终得到的仍是普通字面字符,而非解析后的转义字节。
解决方案
不要拼接转义字符串,直接将十六进制内容转换为原始字节(raw类型)传入iconv即可,这是编码转换场景下最稳妥的实现方式:
s <- "f0c1f0e5" # 拆分十六进制字符串为两位一组,转换为raw字节向量 raw_bytes <- as.raw(strtoi( sapply(seq(1, nchar(s), by = 2), function(i) substr(s, i, i+1)), 16L )) # 直接传入raw向量完成转码 iconv(raw_bytes, from = "IBM01047", to = "ASCII", sub = "?")
执行后即可得到预期输出"0A0V"。
如果一定要解析拼接出的转义字符串,可借助parse()将拼接文本作为R代码解析求值,但该方案存在代码注入风险,仅作参考不推荐日常使用:
s <- "f0c1f0e5" s2 <- sapply(seq(1, nchar(s), by=2), function(x) paste0( "\\x", substr(s, x, x+1)) ) # 拼接为合法R字符串字面量后解析求值 parsed_str <- eval(parse(text = paste0("'", paste(s2, collapse = ""), "'"))) iconv(parsed_str, from="IBM01047", to="ASCII", sub="?")
注意:该方案在输入包含单引号等特殊字符时会直接报错,甚至存在执行恶意代码的风险,优先使用转raw向量的方案。
内容的提问来源于stack exchange,提问作者Ian
相关产品推荐
相关产品推荐

