使用PostgreSQL修剪尾随空格

zga*_*ll1 33 sql postgresql whitespace trim removing-whitespace

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

SELECT TRIM(both ' ' from eventDate) 
FROM EventDates;
Run Code Online (Sandbox Code Playgroud)

然而,尾随空间不会消失.此外,当我尝试修剪日期中的另一个字符(例如数字)时,它也不会修剪.如果我正确阅读手册,这应该有效.有什么想法吗?

Erw*_*ter 61

有许多不同的隐形字符.他们中的许多人都拥有WSpace=YUnicode中的属性("空白").但是一些特殊字符不被视为"空白",仍然没有可见的表示.关于空间(标点符号)空格字符的优秀维基百科文章应该会给你一个想法.

<rant> Unicode在这方面很糟糕:引入了很多充满异国情调的角色,主要是为了让人迷惑.</ rant>

trim()默认情况下,标准SQL 函数仅修剪基本拉丁空格字符(Unicode:U + 0020/ASCII 32).同样的,在rtrim()ltrim()变种.您的通话也只针对该特定角色.

regexp_replace()改为使用正则表达式.

尾随

要删除所有尾随空格(而不是空格的字符串):

SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;
Run Code Online (Sandbox Code Playgroud)

正则表达式解释了:
\s正则表达式类的简写[[:space:]]
    - 这是一组空白字符 - 参见下面的限制
+ ..一个或多个连续匹配
$..字符串的结尾

演示:

SELECT regexp_replace('inner white   ', '\s+$', '') || '|'
Run Code Online (Sandbox Code Playgroud)

返回:

inner white|
Run Code Online (Sandbox Code Playgroud)

是的,这是一个反斜线(\).这个相关答案的细节.

领导

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

regexp_replace(eventdate, '^\s+', '')
Run Code Online (Sandbox Code Playgroud)

^ ..字符串的开头

要删除这两个,您可以链接上面的函数调用:

regexp_replace(regexp_replace(eventdate, '^\s+', ''), '\s+$', '')
Run Code Online (Sandbox Code Playgroud)

或者,您可以在一个呼叫中将两个分支组合在一起.
添加'g'为第4个参数来替换所有匹配,而不仅仅是第一个:

regexp_replace(eventdate, '^\s+|\s+$', '', 'g')
Run Code Online (Sandbox Code Playgroud)

但通常应该更快substring():

substring(eventdate, '\S(?:.*\S)*')
Run Code Online (Sandbox Code Playgroud)

\S.. 除了空白之外的所有东西非捕获括号的集合 ..任何0-n字符的字符串
(?:re)
.*

或者其中一个:

substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)')
Run Code Online (Sandbox Code Playgroud)

(re).. 捕获一组括号

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

空白?

还有一些相关的字符在Unicode中未被归类为"空白" - 因此不包含在字符类中[[:space:]].

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

SELECT E'\u180e', E'\u200B', E'\u200C', E'\u200D';

'?' | '?' | '?' | '?'
Run Code Online (Sandbox Code Playgroud)

另外两个,在pgAdmin中打印为可见字形,但在我的浏览器中不可见:"word joiner","零宽度不间断空格":

SELECT E'\u2060', E'\uFEFF';
'?' | ''
Run Code Online (Sandbox Code Playgroud)

最终,字符是否呈现为不可见还取决于用于显示的字体.

要删除所有这些,请替换'\s''[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]''[\s?????]'(注意尾随不可见的字符!).
示例,而不是:

regexp_replace(eventdate, '\s+$', '')
Run Code Online (Sandbox Code Playgroud)

使用:

regexp_replace(eventdate, '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]+$', '')
Run Code Online (Sandbox Code Playgroud)

要么:

regexp_replace(eventdate, '[\s?????]+$', '')  -- note invisible characters
Run Code Online (Sandbox Code Playgroud)

限制

还有Posix字符类[[:graph:]]应该代表"可见字符".例:

substring(eventdate, '([[:graph:]].*[[:graph:]])')
Run Code Online (Sandbox Code Playgroud)

它可以在每个设置中可靠地处理ASCII字符(其归结为[\x21-\x7E]),但除此之外,您当前(包括第10页)依赖于底层操作系统(定义ctype)提供的信息以及可能的区域设置.

严格地说,对于每个对字符类的引用都是这种情况,但似乎与不太常用的字符类(例如图形)有更多不同意见.但是您可能需要在字符类[[:space:]](简写\s)中添加更多字符以捕获所有空格字符.我爱:\u2007,\u202f并且\u00a0似乎也失踪了@XiCoN JFS.

手册:

在括号表达式中,括在的字符类的名称 [::]代表属于该类的所有字符的列表.标准字符类的名字有:alnum,alpha,blank,cntrl, digit,graph,lower,print,punct,space,upper,xdigit.这些代表ctype中定义字符类.区域设置可以提供其他人.

大胆强调我的.

还要注意Postgres 10修复的这个限制:

修复正则表达式对大字符代码的字符类处理,特别是上面的Unicode字符U+7FF(Tom Lane)

以前,这些字符从未被识别为属于依赖于语言环境的字符类,例如[[:alpha:]].


Art*_*amz 8

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

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

SELECT RTRIM(eventDate) 
FROM EventDates;
Run Code Online (Sandbox Code Playgroud)

这是一个小测试,旨在向您展示它是否有效。告诉我们是否有效!


Cod*_*lan 5

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

 SELECT '(' || REGEXP_REPLACE(eventDate, E'[[:space:]]', '', 'g') || ')' 
 FROM EventDates;
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,我将返回值限制在()中,这样您就可以轻松地看到正则表达式替换在 psql 提示符中工作。因此,您需要删除代码中的那些内容。

  • 这不会在*尾随*空格处停止,而是杀死字符串中的所有空白字符。 (3认同)