PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Trimmen Sie nachgestellte Leerzeichen mit PostgreSQL

Es gibt viele verschiedene unsichtbare Charaktere. Viele von ihnen haben die Eigenschaft WSpace=Y ("Leerzeichen") in Unicode. Einige Sonderzeichen werden jedoch nicht als "Leerzeichen" betrachtet und haben immer noch keine sichtbare Darstellung. Die hervorragenden Wikipedia-Artikel über Leerzeichen (Interpunktion) und Leerzeichen sollten Ihnen eine Vorstellung davon geben.

Unicode ist in dieser Hinsicht scheiße:Es werden viele exotische Zeichen eingeführt, die hauptsächlich dazu dienen, die Leute zu verwirren.

Das Standard-SQL trim() -Funktion schneidet standardmäßig nur das grundlegende lateinische Leerzeichen ab (Unicode:U+0020 / ASCII 32). Dasselbe gilt für rtrim() und ltrim() Varianten. Ihr Anruf zielt auch nur auf diesen bestimmten Charakter ab.

Verwenden Sie reguläre Ausdrücke mit regexp_replace() stattdessen.

Nachlaufend

Um alle nachgestellten Leerzeichen zu entfernen (aber kein Leerraum innerhalb die Zeichenkette):

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

Erklärung des regulären Ausdrucks:
\s ... Klassenkürzel für reguläre Ausdrücke für [[:space:]]
    – das ist der Satz von Leerzeichen – siehe Beschränkungen unten
+ ... 1 oder mehr aufeinanderfolgende Übereinstimmungen
$ ... Ende der Zeichenkette

Demo:

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

Rückgabe:

inner white|

Ja, das ist eine Single Backslash (\ ). Details in dieser verwandten Antwort:

  • SQL auswählen, wo die Spalte mit \
  • beginnt

Führend

Um alle führenden Leerzeichen zu entfernen (aber keine Leerzeichen innerhalb der Zeichenfolge):

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

^ .. Beginn der Zeichenkette

Beides

Um beide zu entfernen , können Sie die obigen Funktionsaufrufe verketten:

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

Oder Sie kombinieren beides in einem einzigen Aufruf mit zwei Nebenstellen .
Fügen Sie 'g' hinzu als 4. Parameter, um alle Übereinstimmungen zu ersetzen, nicht nur die erste:

regexp_replace(eventdate, '^\s+|\s+$', '', 'g')

Aber das sollte normalerweise mit substring() schneller gehen :

substring(eventdate, '\S(?:.*\S)*')

\S ... alles außer Leerraum
(?: re ) ... nicht erfassender Klammersatz
.* ... eine beliebige Folge von 0-n Zeichen

Oder eines davon:

substring(eventdate, '^\s*(.*\S)')
substring(eventdate, '(\S.*\S)')  -- only works for 2+ printing characters

( re ) ... Klammersatz erfassen

Nimmt effektiv das erste Nicht-Leerzeichen und alles bis zum letzten Nicht-Leerzeichen, falls verfügbar.

Leerzeichen?

Es gibt ein paar weitere verwandte Zeichen, die in Unicode nicht als "Whitespace" klassifiziert sind - also nicht in der Zeichenklasse [[:space:]] enthalten sind .

Diese werden als unsichtbare Glyphen in pgAdmin für mich gedruckt:"mongolian vowel", "zero width space", "zero width non-joiner", "zero width joiner":

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

'᠎' | '​' | '‌' | '‍'

Zwei weitere, die als sichtbar gedruckt werden Glyphen in pgAdmin, aber unsichtbar in meinem Browser:"word joiner", "zero width non-breaking space":

SELECT E'\u2060', E'\uFEFF';
'⁠' | ''

Ob Zeichen unsichtbar gemacht werden oder nicht, hängt letztendlich auch von der verwendeten Schriftart ab.

Um alle diese zu entfernen Ersetzen Sie außerdem '\s' mit '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]' oder '[\s᠎​‌‍⁠]' (Nachgestellte unsichtbare Zeichen beachten!).
Beispiel, statt:

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

verwenden:

regexp_replace(eventdate, '[\s\u180e\u200B\u200C\u200D\u2060\uFEFF]+$', '')

oder:

regexp_replace(eventdate, '[\s᠎​‌‍⁠]+$', '')  -- note invisible characters

Einschränkungen

Es gibt auch die Posix-Zeichenklasse [[:graph:]] soll "sichtbare Zeichen" darstellen. Beispiel:

substring(eventdate, '([[:graph:]].*[[:graph:]])')

Es funktioniert zuverlässig für ASCII-Zeichen in jedem Setup (wobei es auf [\x21-\x7E] hinausläuft ), aber darüber hinaus sind Sie derzeit (inkl. Seite 10) auf Informationen angewiesen, die vom zugrunde liegenden Betriebssystem bereitgestellt werden (um ctype zu definieren ) und möglicherweise Gebietsschemaeinstellungen.

Genau genommen gilt das für jeden Verweis auf eine Zeichenklasse, aber es scheint mehr Meinungsverschiedenheiten mit den weniger gebräuchlichen wie graph zu geben . Möglicherweise müssen Sie jedoch weitere Zeichen zur Zeichenklasse [[:space:]] hinzufügen (Kurzform \s ), um alle Leerzeichen abzufangen. Wie:\u2007 , \u202f und \u00a0 scheinen auch für @XiCoN JFS zu fehlen.

Das Handbuch:

Innerhalb eines Klammerausdrucks der Name einer Zeichenklasse, eingeschlossen in [: und :] steht für die Liste aller Zeichen, die zu dieser Klasse gehören. Standard-Zeichenklassennamen sind:alnum , alpha , blank , cntrl ,digit , graph , lower , print , punct , space , upper , xdigit .Diese stehen für die in ctype definierten Zeichenklassen. Ein Gebietsschema kann andere bereitstellen.

Fettdruck von mir.

Beachten Sie auch diese Einschränkung, die mit Postgres 10 behoben wurde:

Korrigieren Sie die Behandlung von Zeichenklassen regulärer Ausdrücke für große Zeichencodes, insbesondere Unicode-Zeichen über U+7FF (Tom Lane)

Bisher wurden solche Zeichen nie als zu Gebietsschema-abhängigen Zeichenklassen wie [[:alpha:]] erkannt .