使用PostgreSQL修剪尾随空格

时间:2014-03-27 21:25:29

标签: sql postgresql whitespace trim removing-whitespace

我有一个包含尾随空格的列eventDate。我试图用PostgreSQL函数TRIM()删除它们。更具体地说,我正在运行:

SELECT TRIM(both ' ' from eventDate) 
FROM EventDates;

但是,尾随空格不会消失。此外,当我尝试修剪日期中的另一个字符(例如数字)时,它也不会修剪。如果我正确地阅读the manual,这应该有效。有什么想法吗?

5 个答案:

答案 0 :(得分:60)

有许多不同的隐形字符。其中许多都具有Unicode中的属性WSpace=Y(“空白”)。但是一些特殊字符不被视为“空白”,仍然没有可见的表示。关于space (punctuation)whitespace characters的优秀维基百科文章应该会给你一个想法。

< rant> Unicode在这方面很糟糕:引入了许多主要用来混淆人们的异国情调。< / rant>

默认情况下,

The standard SQL trim() function仅修剪基本的拉丁空格字符(Unicode:U + 0020 / ASCII 32)。与rtrim() and ltrim()变体相同。您的电话也只针对该特定角色。

使用带regexp_replace()的正则表达式。

尾随

要删除所有尾随空格 (但字符串中没有空格):

SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;

正则表达式解释:
\s .. regular expression class shorthand for [[:space:]]
- 这是一组空格字符 - 请参阅下面的限制
+ ..连续1场或多场比赛 $ ..字符串结尾

演示:

SELECT regexp_replace('inner white   ', '\s+$', '') || '|'

返回:

inner white|

是的,这是一个单个反斜杠(\)。这个相关答案的细节。

龙头

要删除 所有前导空格 (但不是字符串中的空格):

regexp_replace(eventdate, '^\s+', '')

^ ..字符串的开头

两个

要删除 两者 ,您可以链接上述函数调用:

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
.* ..任意0-n字符串

或其中一个:

substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)')

( re ) .. Capturing set of parentheses

有效地获取第一个非空白字符以及最后一个非空格字符(如果可用)。

空白?

还有一些related characters which are not classified as "whitespace" in Unicode - 因此未包含在字符类[[:space:]]中。

这些在pgAdmin中打印为隐形字形对我来说:“mongolian元音”,“零宽度空间”,“零宽度非连接”,“零宽度连接器”:

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页)依赖于底层操作系统提供的信息(定义{{​​1可能是语言环境设置。

严格来说,每个对字符类的引用都是如此,但似乎与不常用的 graph 之间存在更多不同意见。但您可能需要在字符类ctype(简写[[:space:]])中添加更多字符以捕获所有空格字符。 Like: \u2007, \u202f and \u00a0 seem to also be missing for @XiCoN JFS

The manual:

  

在括号表达式中,括起来的字符类的名称   \s[:代表属于该字符的所有字符的列表   类。标准字符类名称为::]alnumalphablank,   cntrldigitgraphlowerprintpunctspaceupper。   它们代表ctype中定义的字符类。   区域设置可以提供其他区域。

大胆强调我的。

另请注意此限制为fixed with Postgres 10

  

修复大字符的正则表达式字符类处理   代码,尤其是xdigit以上的Unicode字符(Tom Lane)

     

以前,这些角色从未被认为属于   依赖于语言环境的字符类,例如U+7FF

答案 1 :(得分:2)

它应该按照你处理它的方式工作,但是在不知道具体字符串的情况下很难说。

如果您只修剪前导空格,则可能需要使用更简洁的形式:

SELECT RTRIM(eventDate) 
FROM EventDates;

这是一个little test,向您展示它有效。 告诉我们它是否成功!

答案 2 :(得分:2)

如果您的空白不仅仅是space元值,那么您需要使用regexp_replace

 SELECT '(' || REGEXP_REPLACE(eventDate, E'[[:space:]]', '', 'g') || ')' 
 FROM EventDates;

在上面的例子中,我绑定了()中的返回值,这样您就可以轻松查看正则表达式替换在psql提示符下工作。因此,您希望删除代码中的内容。

答案 3 :(得分:0)

SELECT  replace(('       devo    system      ') ,' ','');

它给出:devosystem

答案 4 :(得分:0)

经过测试,效果很好:

UPDATE company SET name = TRIM (BOTH FROM name) where id > 0