How to extract real name, first name, lastname, and create nickname from name that have acronyms, aristocratic title, academic titles/degrees

Viewed 160

I am trying to extract name, firstname, lastname, create nickname/firstname, and nickname/lastname from name list that have acronyms, aristocratic title, academic titles/degrees, nickname inside parentheses or after slash-backslash in libreoffice calc using regex function. This is the expected result

expected result

The rules are:

  1. Expected Name: remove nickname inside parentheses or after slash-backslash if exist, job titles, academic titles and degrees except for (R) or (R.), (Ra) or (Ra.), and one alphabet with(out) dot in the name ex: (A.) (A), (M.), and name acronym with(out) dot ex: (Muh.), (Moh), etc
  2. Firstname: (from expected name) extract first name including dot in acronym ex: (R.), (Ra.), (Muh.) and one alphabet with(out) dot in the name ex: (A.) (A), (M.)
  3. Lastname: (from expected name) extract last name including dot
  4. Nickname-fname: from Input Name, extract nickname inside parentheses or after slash-backslash if exist. If not exist, extract first name that is not: one char, acronym with(out) dot, "I Gede", "I Gusti", "I Made", "Ni Luh Putu", or "Ni Putu". If not exist, use next word in name even it's last word. If the name consist only one word, extract it even only one character
  5. Nickname-lname: from Input Name, extract nickname inside parentheses or after slash-backslash if exist. If not exist, extract last name that is not: one char or acronym with(out) dot. If not exist, extract prev word in name even it's first word. If the name consist only one word, extract it even only one character

I tried the following:

=REGEX($A2,"\(.*?\)|\([^)]*\)|\\[^\\]*$|\/[^\/]*$|,.*","")

to extract real name. It remove nickname inside parentheses or after slash-backslash with(out) space like

( Nita ) in Yunita ( Nita )
( Nita ) in Yunita( Nita )
(Nita) in  Yunita (Nita)
(Nita) in  Yunita(Nita)
( Nita) in  Yunita ( Nita)
( Nita) in  Yunita( Nita)
(Nita ) in  Yunita (Nita )
(Nita ) in  Yunita(Nita ))
\Nita in  Yunita\Nita
\ Nita in  Yunita\ Nita
\Nita in  Yunita \Nita
 \ Nita in  Yunita \ Nita
...
and so on

it also remove academic degrees like Ph.D. but it failed on Ra. Ayu S. Ph.D. (because there is no comma after S.). It failed on Prof. and Dr.. I want to keep Ra..

=REGEX($A23,"(?:^|(?:[.!?]\s))([\w.]+)")

to extract first name but failed on Moh.Ali (yes, without space after dot).

=REGEX($A23,"\b(?<last>[\w\[.\]\\]+)$")

to extract last name but also failed on Moh.Ali.

=REGEX($A2,"(\(.*?\)|\([^)]*\)|\\[^\\]*$|\/[^\/]*$)|(\b(?<first>\w+)$)")

to create nickname extracted from given nickname inside parentheses or after slash or backslash. If nickname not exist create one from first name that is not: one char, acronym with(out) dot, "I Gede", "I Gusti", "I Made", "Ni Luh Putu", or "Ni Putu". If the first name not meet condition, use next word in name even it's last word. If still not meet condition, use name that consist only one word, extract it even only one character. The regex failed in most case.

=REGEX($A2,"(\(.*?\)|\([^)]*\)|\\[^\\]*$|\/[^\/]*$)|(\b(?<last>\w+)$)")

to create nickname extracted from given nickname inside parentheses or after slash or backslash. If nickname not exist create one from last name that is not: one char, acronym with(out) dot. If the last name not meet condition, use prev word in name even it's first word. If still not meet condition, use name that consist only one word, extract it even only one character. It failed in most case too.

This is the result of the regex:

trial result

But I'm new to regex and stuck. Please help me

1 Answers

The parsing rules are rather elaborate, especially for nicknames, so I suggest using a multi-step process involving 2 helper columns and the non-advanced (POSIX ERE plus \b) features of the available ICU regular expressions combined with a few spreadsheet formulas.

If you copy the formulas listed and commented below to columns B through H in your spreadsheet you should find that conditional formatting highlights a total of 5 cells, all nicknames: 1 for Jasmine, 2 for Imah, and 2 for Nur.. For the first 3 the expected result contradicts the nickname rules; removing the dot in Nur. is left as an exercise.

I used the input as it is but in cases like this pre-processing is the key to avoid complex or special-case regexes, e.g. insert a blank in names like M.Ali, or prefix a comma to comma-less Ph.D..

Aside: When you post source data as an image rather than plaintext what's the likelihood of someone OCR'ing the image and editing the text?


Step 1

Add auxiliary column AuxSplit separating the input string into its 3 main groups -- name, titles, nickname (last 2 optional) -- and joining them with @. NB: @ is used for this reply but it must be a non-meta character not appearing in any input string.

REGEX(A22;"(.*?)( *(Ph\.D\.)?|(,[^\\/(]*?))?( *[\\/(].*)? *$";"$1@$2@$5")

where

  • $ anchors regex to end of string
  • $5 is the captured optional nickname (incl. any delimiters and blanks)
  • $2 the optional suffixed titles (incl. any comma and blanks); note that the comma-less Ph.D is special-cased
  • $1 the name (incl. any leading blanks)

Sample content: Jasmine Fianna@, B.A., M.A.@/Jasmine


Step 2

Add auxiliary column AuxNick extracting an explicit nickname (if any) from 3rd main group (after last @) in AuxSplit.

REGEX(G22;".*@[\\/( ]*([^ )]*)[ )]*$";"$1")

Capturing string after \ or / or between (), trimming off blanks.

Sample content Agus.


Step 3

Extract ExpectedName from 1st group (up to first @) in AuxSplit stripping off any prefixed titles.

REGEX(G22;"^((Prof|Dr)\.[ ]*)?([^@]*).*";"$3")

Note that these titles are special-cased as they have the same form as an abbreviated name.

Sample content: Q. Ranita El


Step 4

From ExpectedName extract Firstname,

REGEX(B22;"^(Ra?\.?|[^.]+\.|[^ ]+)")

stripping off R/R./Ra/Ra. and blanks from start of string,

and Lastname

REGEX(B22;"[^ .]*[^ ]$")

extracting the last character sequence after blank/dot; any trailing blanks were removed in step 1.

Note: with M.Ali as M. Ali simplify Lastname formula to REGEX(B22;"[^ ]+$")


Step 5

Extract Lastnick from AuxNick, LastName, or ExpectedName

IF(LEN(H22);H22;IF(ISNA(REGEX(D22;"\b([^ ]+\.|[^ .])$"));D22;REGEX(B22;".*?([^ ]+)[ ]+([^ ]*\.|[^.])$";"$1")))
  • IF(LEN(H22);H22 : use explicit nickname if present
  • ;IF(ISNA(REGEX(D22;"…";D22 : else use Lastname unless abbrev. or 1-char.
  • ;REGEX(B22;"…";"$1"))) : else use previous word in name, exploiting the fact that an unmatched replacement returns the entire string

and Firstnick from AuxNick, FirstName, or ExpectedName

IF(LEN(H22);H22;IF(ISNA(REGEX(B22;"^([^ ]+\.|[^ ]\b|I (Gede|Gusti|Made)\b|Ni (Luh )?Putu\b)"));C22;REGEX(B22;"^(I (Gede|Gusti|Made)\b|Ni (Luh )?Putu\b|.*?)[ .]\b([^ ]+).*";"$4")))
  • IF(LEN(H22);H22 : use explicit nickname if present
  • ;IF(ISNA(REGEX(B22;"…";C22 : else use FirstName unless abbrev. / 1-char. / special case
  • ;REGEX(B22;"…";"$4"))) : else use next word in name, exploiting the fact that an unmatched replacement returns the entire string

TODO: remove trailing dot from Nur.

Recall the (LibreOffice 6.2+) REGEX syntax:

*Syntax*: REGEX( Text ; Expression [ ; [ Replacement ] [ ; Flags|Occurrence ] ] )
*Expression*: A text representing the regular expression, using [ICU](https://unicode-org.github.io/icu/userguide/strings/regexp.html) regular expressions. If there is no match and Replacement is not given, #N/A is returned.

Replacement: Optional. The replacement text and references to capture groups. If there is no match, Text is returned unmodified.

Related