【问题标题】:Trim trailing spaces with PostgreSQL使用 PostgreSQL 修剪尾随空格
【发布时间】:2014-05-07 03:07:16
【问题描述】:

我有一列 eventDate 包含尾随空格。我正在尝试使用 PostgreSQL 函数 TRIM() 删除它们。更具体地说,我正在跑步:

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

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

【问题讨论】:

  • 你确定它实际上是一个space 字符而不是其他一些不可见的空白字符吗?
  • @CodyCaughlan 你是对的。这是其他一些不可见的空白字符。
  • 你是如何修复这个不可见字符的

标签: sql postgresql whitespace trim removing-whitespace


【解决方案1】:

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

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

SELECT RTRIM(eventDate) 
FROM EventDates;

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 这不会在 尾随 个空格处停止,而是会删除字符串中的所有空白字符。
    【解决方案3】:

    有许多不同的隐形字符。他们中的许多人在 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:

    在括号表达式中,字符类的名称包含在 [::] 代表属于那个的所有字符的列表 班级。标准字符类名称为:alnumalphablankcntrldigitgraphlowerprintpunctspaceupperxdigit。 这些代表 ctype 中定义的 字符类。 语言环境可以提供其他语言环境。

    我的大胆强调。

    还要注意这个限制是fixed with Postgres 10

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

    以前,此类字符从未被识别为属于 与语言环境相关的字符类,例如 [[:alpha:]]

    【讨论】:

    • 所以...SELECT regexp_replace(regexp_replace(eventdate, '^\s+', ''), '\s+$', '') FROM eventdates; 会去除所有前导和尾随空格吗?
    • @heliotrope;如果只是“空格”,请使用trim()。否则,请考虑上面添加的部分。
    • @ErwinBrandstetter 最后一个 SQL 查询有一个额外的右括号。
    • @NickeManarin:谢谢,已修复。
    • 对于修剪 Non-breaking spaces 以及(对于 UTF-8 编码的 PostreSQL-DB),请执行 SELECT regexp_replace(regexp_replace(eventdate, '^(\s|\u00a0|\ufeff|\u2007|\u180e|\u202f)+', ''), '(\s|\u00a0|\ufeff|\u2007|\u180e|\u202f)+$', '') FROM eventdates;
    【解决方案4】:
    SELECT  replace(('       devo    system      ') ,' ','');
    

    它给出:devosystem

    【讨论】:

      【解决方案5】:

      一个经过测试的像魅力一样工作的人:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-26
        • 1970-01-01
        • 2011-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        • 2017-01-07
        相关资源
        最近更新 更多