如何从字符串中删除不可打印的不可见字符?

Sur*_*rya 3 ruby string replace ruby-2.4

如何从字符串中删除不可打印的不可见字符?

红宝石版本:2.4.1

2.4.1 :209 > product.name.gsub(/[^[:print:]]/,'.')
 => "Kanha?" 
2.4.1 :210 > product.name.gsub(/[^[:print:]]/,'.').length
 => 6 

2.4.1 :212 > product.name.gsub(/[\u0080-\u00ff]/, '').length
 => 6 

2.4.1 :214 > product.name.chars.reject { |char| char.ascii_only? and (char.ord < 32 or char.ord == 127) }.join.length
 => 6 

2.4.1 :216 > product.name.gsub(/[^[:print:]]/i, '').length
 => 6 
Run Code Online (Sandbox Code Playgroud)

“Kanha”这个词有5个字母。但是,有第 6 个字符不可打印。我怎样才能删除它?

通过谷歌搜索和 SOing,我已经尝试了几种方法,但正如您所见,这些方法都没有帮助。

当我尝试将数据与其他系统集成时,它会引起问题。

Jor*_*ing 6

首先,让我们弄清楚违规角色是什么:

str = "Kanha?"
p str.codepoints
# => [75, 97, 110, 104, 97, 8236]
Run Code Online (Sandbox Code Playgroud)

前五个代码点介于 0 和 127 之间,这意味着它们是 ASCII 字符。可以安全地假设它们是字母 Kanha,尽管如果您愿意,这很容易验证:

p [75, 97, 110, 104, 97].map(&:ord)
# => ["K", "a", "n", "h", "a"]
Run Code Online (Sandbox Code Playgroud)

这意味着有问题的字符是最后一个,即代码点 8236。不过,这是一个十进制(基数为 10)的数字,而 Unicode 字符通常按其十六进制(基数为 16)数字列出。8236 的十六进制是 202C ( 8236.to_s(16) # => "202c"),所以我们只需要谷歌搜索 U+202C

谷歌很快告诉我们有问题的字符是U+202C POP DIRECTIONAL FORMATTING并且它是 Unicode 字符“其他,格式”类别的成员。维基百科是这样的:

包括软连字符、连接控制字符(zwnj 和 zwj)、支持双向文本的控制字符和语言标记字符

它还告诉我们类别的“值”或代码是“Cf”。如果这些听起来像是您想从字符串中删除的字符以及 U+202C,您可以在 Ruby 正则表达式中使用\p{Cf}属性。您还可以使用\P{Print}(注意大写P)作为等价物[^[:print]]

str = "Kanha?"
p str.length # => 6

p str.gsub(/\P{Print}|\p{Cf}/, '') # => "Kahna"
p str.gsub(/\P{Print}|\p{Cf}/, '').length # => 5
Run Code Online (Sandbox Code Playgroud)

在 repl.it 上查看:https ://repl.it/@jrunning/DutifulRashTag

  • 太感谢了。这样可行。你怎么发现这是问题所在? (2认同)