有许多不同的隐形字符。他们中的许多人在 Unicode 中都有属性WSpace=Y(“空白”)。但是一些特殊字符不被认为是“空白”并且仍然没有可见的表示。关于space (punctuation) 和whitespace characters 的优秀维基百科文章应该会给你一个想法。
Unicode 在这方面很糟糕:引入了许多主要用来迷惑人们的奇异字符。
The standard SQL trim() function 默认只修剪基本的拉丁空格字符(Unicode:U+0020 / ASCII 32)。与rtrim() and ltrim() 变体相同。您的调用也仅针对该特定角色。
改用带有regexp_replace() 的正则表达式。
尾随
要删除所有尾随空格(但不是字符串内的空格):
SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;
正则表达式解释:
\s ...正则表达式class shorthand for [[:space:]]
- 这是一组空白字符 - 请参阅下面的限制
+ ... 1 个或多个连续匹配
$ ... 字符串结尾
演示:
SELECT regexp_replace('inner white ', '\s+$', '') || '|'
返回:
inner white|
是的,这是一个单个反斜杠(\)。此相关答案中的详细信息:
领先
要删除所有前导空格(但不是字符串内的空格):
regexp_replace(eventdate, '^\s+', '')
^ .. 字符串开始
两者
要删除 both,您可以链接上面的函数调用:
regexp_replace(regexp_replace(eventdate, '^\s+', ''), '\s+$', '')
或者您可以在一个电话中将两者与两个 branches 结合起来。
添加'g' 作为第四个参数来替换所有匹配项,而不仅仅是第一个:
regexp_replace(eventdate, '^\s+|\s+$', '', 'g')
但是使用substring() 通常应该更快:
substring(eventdate, '\S(?:.*\S)*')
\S ...一切但空白
(?:re) ... non-capturing set of parentheses
@987654362 @ ... 任何 0-n 个字符的字符串
或其中之一:
substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)') -- only works for 2+ printing characters
(re) ... Capturing set of parentheses
有效地获取第一个非空白字符以及直到最后一个非空白字符(如果可用)的所有内容。
空格?
还有几个related characters which are not classified as "whitespace" in Unicode - 所以不包含在字符类[[:space:]]中。
对我来说,这些在 pgAdmin 中打印为不可见的字形:“蒙古元音”、“零宽度空格”、“零宽度非连接符”、“零宽度连接符”:
SELECT E'\u180e', E'\u200B', E'\u200C', E'\u200D';
'' | '' | '' | ''
另外两个,在 pgAdmin 中打印为 可见 字形,但在我的浏览器中不可见:“word joiner”、“零宽度不间断空格”:
SELECT E'\u2060', E'\uFEFF';
'' | ''
最终,字符是否呈现为不可见还取决于用于显示的字体。
要删除所有这些,请将'\s' 替换为'[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' 或'[\s]'(注意尾随不可见字符!)。
示例,而不是:
regexp_replace(eventdate, '\s+$', '')
使用:
regexp_replace(eventdate, '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]+$', '')
或:
regexp_replace(eventdate, '[\s]+$', '') -- note invisible characters
限制
还有Posix character class [[:graph:]] 应该代表“可见字符”。示例:
substring(eventdate, '([[:graph:]].*[[:graph:]])')
它在每个设置中都能可靠地处理 ASCII 字符(归结为[\x21-\x7E]),但除此之外,您目前(包括第 10 页)依赖于底层操作系统提供的信息(定义ctype)和可能是区域设置。
严格来说,每个对一个字符类的引用都是如此,但似乎与像graph这样不太常用的引用有更多的分歧。但是您可能必须向字符类[[:space:]](简写\s)添加更多字符才能捕获所有空白字符。 Like: \u2007, \u202f and \u00a0 seem to also be missing for @XiCoN JFS.
The manual:
在括号表达式中,字符类的名称包含在
[: 和 :] 代表属于那个的所有字符的列表
班级。标准字符类名称为:alnum、alpha、blank、cntrl、
digit、graph、lower、print、punct、space、upper、xdigit。
这些代表 ctype 中定义的 字符类。
语言环境可以提供其他语言环境。
我的大胆强调。
还要注意这个限制是fixed with Postgres 10:
修复正则表达式对大字符的字符类处理
代码,尤其是 U+7FF 以上的 Unicode 字符(Tom Lane)
以前,此类字符从未被识别为属于
与语言环境相关的字符类,例如 [[:alpha:]]。