2017-02-02 2 views
1

AnforderungRegex zu verschiedenen Gruppen entsprechen je nach String Inhalt

Ich habe eine Postgres-Spaltenwerte in zwei Formen enthalten: Namen persönliche und Corporate. Persönliche Namen enthalten ein Komma, während Firmennamen dies nicht tun.

_owner_titlecase 
------------------------- 
McCartney, James Paul 
Lennon, John Winston Ono 
Harrison, George 
Starkey, Richard 
The Beatles 

Ich habe eine Abfrage zu erzeugen, die nur die persönlichen Namen abkürzt, wie folgt aus:

regexp_replace 
------------------------- 
McCartney, J P 
Lennon, J W O 
Harrison, G 
Starkey, R 
The Beatles 

Hintergrund

Nach einigen Leistungstests, erkannte ich, habe ich kann nicht Verwenden Sie CASE, um die zwei Zeilentypen anders zu behandeln (wie in CASE WHEN _owner_titlecase ~ ',' regexp_replace...). Ich hoffe also, dass es einen Weg gibt, eine einzige Regex zu schreiben, die beide Arten unterschiedlich behandeln kann.

ich previously asked darüber, wie der Initialen Namensbestandteil zu handhaben, und jetzt sind mit (^\w+)|\Y\w Regex wie folgt:

, regexp_replace(_owner_titlecase 
    , '(^|;\s+)(\w+)|\Y\w' 
    , '\1', 'g') 

Jetzt habe ich den Umfang weitet sie bei den Firmennamen zu suchen, natürlich The Beatles wird abgekürzt zu The B.

Die \Y ist eine Postgres regex Zeichenklasse, die ich über here gelernt habe, die nur an einem Punkt übereinstimmt, der nicht der Anfang oder das Ende eines Wortes ist. Während die speziellen Postgres-Klassen so aussehen, als könnten sie in dieser Situation nützlich sein, wäre es eigentlich nützlich, bei Regex-Features zu bleiben, die universell sind, so dass ich sie an Orten wie regex101.com testen kann. Derzeit sind meine einzigen Postgres-Testplattformen etwas peinlich und bieten keine Debugging-Hilfe.

Die ganze Geschichte ist, dass wir eine CartoDB-Karte haben, auf der wir eine Ebene überlagern wollen, die Eigentümernamen enthält. Einige Eigenschaften liegen nahe beieinander, und die Liste der Eigentümernamen kann lang sein, weshalb die Abkürzung erforderlich ist.

+2

Ich glaube, dass Sie '^ ([^,] *) $ | (^ |; \ s +) (\ w +) | \ Y \ w' Muster verwenden und durch' '\ 1 \ 2 \ 3'' ersetzen können –

+0

Nochmals vielen Dank @Wictor. Dies funktioniert für die meisten persönlichen Namen. Es bringt O'Brien, John Andrew nicht ganz recht. – OutstandingBill

+0

Ich verstehe das Problem vielleicht nicht richtig, aber konnte man nicht einfach mit einer 'where'-Anweisung filtern, wie' WHERE name LIKE%,% ' – Fallenhero

Antwort

1

Ich schlage vor, dass Sie

regexp_replace(_owner_titlecase, 
    '^([^,]*)$|(^|;\s+)([\w\u0027]+)|\Y\w', 
    '\1\2\3', 'g') 

Der Punkt verwenden sollte, ist, dass Sie nur ein beliebiges Wort char entfernen müssen, die mit einem Wort char vorangestellt ist, und halten alles andere. So kann jede Ausnahme (Text, den Sie behalten müssen) als erfasster alternativer Zweig vor dem Muster hinzugefügt werden, das Sie entfernen müssen.

Der ^([^,]*)$ Teil entspricht nur einer Zeichenfolge, die aus 0+ Zeichen außer , besteht, und erfasst sie, und mit \1 wird sie im Ersatzergebnis wiederhergestellt.

+0

Die 'O'Brien, Andrew John' Problem (die wieder als' O'B, AJ' kommt) durch die Verlängerung der Muster leicht befestigt ist leicht zu '^ ([^] *) $ | (^ |; \ s +) ([\ w \ u0026] +) | \ Y [\ w \ u0027] '. Ich bin mir aber nicht sicher, welche Seite des '|' dafür verantwortlich ist. – OutstandingBill

+1

Ich denke, die '\ u0027' im letzten Zweig ist nicht notwendig. Siehe ['^ ([^,] *) $ | (^ |; \ s +) ([\ w \ u0026] +) | \ Y \ w \ Regex-Demo] (https://regex101.com/r/CbydIO/1). Es sieht so aus als wäre das genug. Namen können kein 'O''-Präfix haben. –

Verwandte Themen