Ответ 1
Есть много разных невидимых персонажей. Многие из них имеют свойство WSpace=Y
("пробел") в Unicode. Но некоторые специальные символы не считаются "пробелами" и все еще не имеют видимого представления. Отличная статья в Википедии о пробелах и знаках пробела должна дать вам представление.
<rant> Unicode отстой в этом отношении: вводит множество экзотических персонажей, которые в основном служат, чтобы сбить с толку людей. </rant>
Стандартная функция SQL trim()
по умолчанию обрезает только основной латинский пробел (Unicode: U + 0020/ASCII 32). То же самое с rtrim()
и ltrim()
. Ваш звонок также касается только этого конкретного персонажа.
regexp_replace()
этого используйте регулярные выражения с regexp_replace()
.
Скользящий
Чтобы удалить все конечные пробелы (но не пробелы внутри строки):
SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;
Регулярное выражение объясняет:
\s
.. сокращение класса регулярного выражения для [[:space:]]
- который представляет собой набор символов пробела - см. ограничения ниже +
.. 1 или более последовательных матчей $
.. конец строки
Демо-версия:
SELECT regexp_replace('inner white ', '\s+$', '') || '|'
Возвращает:
inner white|
Да, это один обратный слеш (\
). Подробности в этом связанном ответе.
ведущий
Чтобы удалить все начальные пробелы (но не пробелы внутри строки):
regexp_replace(eventdate, '^\s+', '')
^
.. начало строки
И то и другое
Чтобы удалить оба, вы можете связать вышеупомянутые вызовы функций:
regexp_replace(regexp_replace(eventdate, '^\s+', ''), '\s+$', '')
Или вы можете объединить оба в одном вызове с двумя ответвлениями.
Добавьте 'g'
качестве 4-го параметра, чтобы заменить все совпадения, а не только первый:
regexp_replace(eventdate, '^\s+|\s+$', '', 'g')
Но обычно это происходит быстрее с substring()
:
substring(eventdate, '\S(?:.*\S)*')
\S
.. все, кроме пустого пространства (?:
re
)
Набор без скобок .*
.. любая строка из 0-n символов
Или один из них:
substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)')
(
re
)
.. Захват набор скобок
Эффективно принимает первый непробельный символ и все до последнего непробельного символа, если он доступен.
Пробелы?
Есть еще несколько связанных символов, которые в 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 [[:graph:]]
должен представлять "видимые символы". Пример:
substring(eventdate, '([[:graph:]].*[[:graph:]])')
Он работает надежно для символов ASCII в каждой настройке (где он сводится к [\x21-\x7E]
), но помимо этого вы в настоящее время (включая стр. 10) зависите от информации, предоставленной базовой ОС (для определения ctype
) и возможно настройки локали.
Строго говоря, так обстоит дело с каждой ссылкой на класс символов, но, похоже, больше разногласий с менее часто используемыми, такими как graph. Но вам может понадобиться добавить больше символов в класс символов [[:space:]]
(сокращение \s
), чтобы перехватить все пробельные символы. Например: \u2007
, \u202f
и \u00a0
также отсутствуют в @XiCoN JFS.
В выражении в скобках имя класса символов, заключенное в
[:
и:]
обозначает список всех символов, принадлежащих этому классу. Стандартные имена классов символов:alnum
,alpha
,blank
,cntrl
,digit
,graph
,lower
,punct
,space
,upper
,xdigit
. Они обозначают классы символов, определенные в ctype. Локаль может предоставить другим.
Жирный акцент мой.
Также обратите внимание на это ограничение, которое было исправлено в Postgres 10:
Исправлена обработка класса символов регулярных выражений для кодов больших символов, особенно символов Юникода выше
U+7FF
(Том Лейн)Ранее такие символы никогда не распознавались как принадлежащие классам символов, зависящим от локали, таким как
[[:alpha:]]
.