删除ruby中的奇怪无效字符

23t*_*tux 3 ruby encoding character-encoding special-characters

我有一些XML内容(UTF-8),其中包含无效字符(Line 2190, SyntaxError: PCDATA invalid Char value 15当我尝试解析内容时,nokogiri告诉我Nokogiri::XML(content)).

该字符在Sublime Text编辑器中显示为"SI":

无效字符

当我尝试复制角色时,没有任何东西被复制,所以我甚至无法查找它.当我在我的Atom编辑器中打开它时,不显示"SI".但是,当我使用右键单步执行字符时,我必须键入两次以覆盖放置"SI"字符的位置.

首先,这是什么角色?第二:在Ruby中有没有办法删除这些字符.我尝试过,content.chars.select{|i| i.valid_encoding?}.join但它没有删除角色.

更新

我通过用ruby读取原始文件找到了这个角色.该字符是\u000F"\u000F".ord返回字符代码15.关于http://www.fileformat.info/info/unicode/char/000f/index.htm这是一个SHIFT IN角色.还有其他类似的人物吗?我可以通过使用删除它们str.split("\u000F").join,但如果还有其他这样的字符,这似乎不是一个好方法.有任何想法吗?

jro*_*ind 12

如果字节序列实际上对编码无效(UTF-8),那么在ruby 2.1+中,您可以使用String#scrub方法.默认情况下,它将使用"unicode replacement character"替换无效字符(通常在框中作为问号重新表示),但您也可以使用它来完全删除它们.

但是,正如您所注意到的,您的"奇怪字节"实际上是有效的UTF-8,它重新编写SHIFT IN控制字符unicode代码点"\ u000F" .(很好找出所涉及的实际字节/字符,这是最难的部分!)

因此,如果我们想删除它们,我们必须明确我们所说的"像这样的字符".人物喜欢什么?

Nokogiri抱怨它在XML"PCDATA"(Parsed Character Data)区域中无效.为什么它是合法的unicode/UTF-8,但在XML PCDATA中无效?什么是XML字符数据的合法性?我试图解决这个问题,但它让人感到困惑,因为规范显然说某些角色"气馁"(什么?),并且在我的眼中做出与其他事情相矛盾的陈述.

我不确定Nokogiri将从PCData中删除哪些字符,我们必须查看Nokogiri源(或更可能是libxml源),或尝试询问有关nokogiri/libxml源的更多信息的人的问题.

但是,"\ u000F"是一个"控制字符",你不太可能想要你的XML字符数据中的控制字符(除非你知道你这样做),并且XML规范似乎不鼓励控制字符(显然Nokogiri/libxml实际上不允许它们) ?).因此,解释"像这样的字符"的一种方法是"控制字符".

您可以使用此正则表达式从字符串中删除所有控制字符,例如:

"Some string \u000F more".gsub(/[\u0001-\u001A]/ , '') # remove control chars, unicode codepoints from 0001 to 001A
   # => "Some string  more"
Run Code Online (Sandbox Code Playgroud)

如果我们将"像这样的字符"解释为任何不打印的字符 - 比"控制字符"更广泛的类别,并且将包括一些nokogiri完全没有问题的字体.我们可以通过使用ruby对正则表达式中的unicode字符类的支持来尝试删除一些不仅仅是控制字符:

some_string.gsub(/[^[:print:]]/ , '')
Run Code Online (Sandbox Code Playgroud)

[:print]被描述为相当模糊的"排除控制角色和类似",所以这与我们想要做的模糊规范相匹配.:)

所以它真的取决于我们所说的"像这样的人物".真的,"你喜欢这样的字符"可能意味着"Nokogiri/libxml拒绝允许的任何字符",我担心我实际上没有回答这个问题,因为我不确定并且不能很容易搞清楚.但是对于很多情况,删除控制字符,甚至更好地删除不匹配的字符[:print]可能会很好,除非你有理由想要控制字符和类似的东西(如果你知道你需要它们作为记录分隔符,对于实例).

如果不是删除,你想用unicode替换字符替换它们,这通常用于表示"我们无法处理的字节序列":

"Shift in: \u000F".gsub(/[^[:print:]]/, "\uFFFD")
   # => "Shift in: ?"
Run Code Online (Sandbox Code Playgroud)

如果不是删除它们,你想以某种方式逃避它们,它们可以在XML解析后重建......再次问一下,我会弄清楚,但我现在还没有.:)

欢迎处理字符编码问题,它确实有时会让人感到困惑.