What is the regex that will return single word names with a special character that is a | (pipe)

Viewed 83

I have words like

John | Gilbert | alan
Stephen | king | harris
| | Steve
Barack | | Obama
Tom | George | Stevenson 
Donald | | 
 | Alan | 
Sir | Alex | 
Stewart | | 
John | new | man

I would like to return single words name like below.

Steve
Alan
Stewart

I have tried

Name = re.search('\| (.*)',name)

The above re returns all of them.

4 Answers

You may try using re.findall with the pattern (?:(?<=\n)|(?<=^))\|\s*\|\s*(\S+)(?:\n|$), which will find only single word names:

inp = """| John | Gilbert | alan
| Stephen | king | harris
| | Steve
| Barack | | Obama
|| Donald | | Trump 
| | Alan
| | Stewart"""

single_names = re.findall(r'(?:(?<=\n)|(?<=^))\|\s*\|\s*(\S+)(?:\n|$)', inp)
print(single_names)

This prints:

['Steve', 'Alan', 'Stewart']

A simple modification in your existing regex pattern suffices:

>>> name = """
|| John Deere
|| Stephen king
|| Steve
|| Barack Hussein Obama
|| Donald Trump 
|| Alan
|| Stewart"""
>>> re.findall('\| ([^\s]*)(?:\n|$)', name)
['Steve', 'Alan', 'Stewart']

You can find all the matches using re.findall in your input string.

Edit: For your edited input containing | in between names, this works:

>>> name = """| John | Gilbert | alan
| Stephen | king | harris
| | Steve
| Barack | | Obama
|| Donald | | Trump 
| | Alan
| | Stewart"""
>>> re.findall('^[|\W]*([^\s]+)(?:\n|$)', name, re.MULTILINE)
['Steve', 'Alan', 'Stewart']

You could use

^[|\s]*\|\s*([^|\s]+)$
  • ^ Start of string
  • [|\s]* Match 0+ times either | or a whitespace char
  • \| Match |
  • \s* Match 0+ whitespace chars
  • ([^|\s]+) Capture group 1, match any char except | or a whitspace char
  • $ End of string

Regex demo | Python demo

For example

import re

regex = r"^[|\s]*\|\s*([^|\s]+)$"

names = ("| John | Gilbert | alan\n"
            "| Stephen | king | harris\n"
            "| | Steve\n"
            "| Barack | | Obama\n"
            "|| Donald | | Trump \n"
            "| | Alan\n"
            "| | Stewart")

print(re.findall(regex, names, re.MULTILINE))

Output

['Steve', 'Alan', 'Stewart']

Use

(?m)^(?:\|[^\S\n]*)*(\S+)[^\S\n]*$

See proof.

Explanation

--------------------------------------------------------------------------------
  (?m)                     multiline mode (= re.M / re.MULTILINE)
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (0 or more times
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    \|                       '|'
--------------------------------------------------------------------------------
    [^\S\n]*                 any character except: non-whitespace
                             (all but \n, \r, \t, \f, and " "), '\n'
                             (newline) (0 or more times (matching the
                             most amount possible))
--------------------------------------------------------------------------------
  )*                       end of grouping
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    \S+                      non-whitespace (all but \n, \r, \t, \f,
                             and " ") (1 or more times (matching the
                             most amount possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  [^\S\n]*                 any character except: non-whitespace (all
                           but \n, \r, \t, \f, and " "), '\n'
                           (newline) (0 or more times (matching the
                           most amount possible))
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Python code:

import re
string = """| John | Gilbert | alan
| Stephen | king | harris
| | Steve
| Barack | | Obama
|| Donald | | Trump 
| | Alan
| | Stewart"""
pattern = r"^(?:\|[^\S\n]*)*(\S+)[^\S\n]*$"
print(re.findall(pattern, string, re.M))

Results: ['Steve', 'Alan', 'Stewart']

Related