Има много различни невидими герои. Много от тях имат свойството WSpace=Y
(„прабел“) в Unicode. Но някои специални знаци не се считат за "прабел" и все още нямат видимо представяне. Отличните статии в Уикипедия за интервал (пунктуация) и бели символи трябва да ви дадат представа.
Стандартният SQL trim()
функцията по подразбиране отрязва само основния символ на латински интервал (Unicode:U+0020 / ASCII 32). Същото с rtrim()
и ltrim()
варианти. Вашето обаждане също е насочено само към този конкретен знак.
Използвайте регулярни изрази с regexp_replace()
вместо това.
Завършване
За да премахнете всички крайни бели интервали (но не и бяло пространство вътре низа):
SELECT regexp_replace(eventdate, '\s+$', '') FROM eventdates;
Регулярният израз е обяснен:\s
... съкращаване на класа на регулярни изрази за [[:space:]]
- което е набор от знаци за интервал - вижте ограниченията по-долу +
... 1 или повече последователни съвпадения$
... край на низ
Демо:
SELECT regexp_replace('inner white ', '\s+$', '') || '|'
Връща:
inner white|
Да, това е единично обратна наклонена черта (\
). Подробности в този свързан отговор:
- SQL изберете къде колоната започва с \
Водеща
За да премахнете всички водещи бели интервали (но не празно пространство вътре в низа):
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)') -- only works for 2+ printing characters
(
re
)
... Заснемане на набор от скоби
Ефективно приема първия знак без интервал и всичко до последния знак без интервал, ако е наличен.
Пространство?
Има още няколко свързани знака, които не са класифицирани като "бели интервали" в Unicode - така че не се съдържат в символния клас [[:space:]]
.
Те се отпечатват като невидими глифове в pgAdmin за мен:"монголска гласна", "пространство с нула ширина", "несъединяване с нулева ширина", "дограма с нула ширина":
SELECT E'\u180e', E'\u200B', E'\u200C', E'\u200D';
'' | '' | '' | ''
Още две, отпечатване като видимо глифове в pgAdmin, но невидими в моя браузър:"word joiner", "zero width non-breaking space":
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
) и евентуално локални настройки.
Строго погледнато, това е така за всеки препратка към клас символи, но изглежда има повече несъгласия с по-рядко използваните, като графика . Но може да се наложи да добавите още знаци към класа от знаци [[:space:]]
(съкратено \s
), за да улови всички символи за интервал. Харесайте:\u2007
, \u202f
и \u00a0
изглежда липсва и за @XiCoN JFS.
Ръководството:
В рамките на израз в скоби, името на клас от знаци, затворен в
[:
и:]
означава списък на всички знаци, принадлежащи към този клас. Стандартните имена на класове на знаци са:alnum
,alpha
,blank
,cntrl
,digit
,graph
,lower
,punct
,space
,upper
,xdigit
.Те означават символните класове, дефинирани в ctype. Локалът може да предостави други.
Удебелен акцент мой.
Също така имайте предвид това ограничение, което беше коригирано с Postgres 10:
Коригирайте обработката на класовете на знаците на регулярните изрази за големи кодове на знаци, особено Unicode знаци над
U+7FF
(Том Лейн)Преди това такива знаци никога не са били разпознавани като принадлежащи на зависими от локал класове знаци, като
[[:alpha:]]
.