Skip to content

Instantly share code, notes, and snippets.

@jhyland87
Last active September 9, 2016 20:07
Show Gist options
  • Save jhyland87/54af0ea095244de43bc8ed5beebe206d to your computer and use it in GitHub Desktop.
Save jhyland87/54af0ea095244de43bc8ed5beebe206d to your computer and use it in GitHub Desktop.
import sys
import re
strings = [
'{cols:a,b,c}',
'{range:b-z}',
'{col:A}',
'{cols:a,b,c:,}',
'{range:b-z:,}',
'{col:1}',
'{cols:a,b,c:,}!',
'{range:b-z:,}?',
'{col:1}?'
]
for s in strings:
print "Macro: %s" % s
m = re.match(r"\{(?P<noun>(?:cols?|range))\:(?:(?P<is_multicol>(?<=cols:)(?P<cols>(?:(?:[a-zA-Z]+|[0-9]+)(?:,(?:[a-zA-Z]+|[0-9]+))+))|(?<=range:)(?P<col_start>(?:[a-zA-Z]+|[0-9]+))\-(?P<col_stop>(?:[a-zA-Z]+|[0-9]+)))?|(?<=col:)(?P<col>(?:[a-zA-Z]+|[0-9]+)))(?(is_multicol)(?:\:(?P<joiner>(?:.)))?)\}(?P<modifier>(?:[\?\!]))?", s)
macro_items = m.groupdict()
for key, value in macro_items.iteritems():
if value:
print("\tKey: %s; Val: %s" % ( key, value ))
"""
https://regex101.com/r/qN1kY5/2
OUTPUT:
Macro: {cols:a,b,c}
Key: noun; Val: cols
Key: cols; Val: a,b,c
Key: is_multicol; Val: a,b,c
Macro: {range:b-z}
Key: noun; Val: range
Key: col_start; Val: b
Key: is_multicol; Val: b-z
Key: col_stop; Val: z
Macro: {col:A}
Key: noun; Val: col
Key: col; Val: A
Macro: {cols:a,b,c:,}
Key: joiner; Val: ,
Key: noun; Val: cols
Key: cols; Val: a,b,c
Key: is_multicol; Val: a,b,c
Macro: {range:b-z:,}
Key: joiner; Val: ,
Key: noun; Val: range
Key: col_start; Val: b
Key: is_multicol; Val: b-z
Key: col_stop; Val: z
Macro: {col:1}
Key: noun; Val: col
Key: col; Val: 1
Macro: {cols:a,b,c:,}!
Key: joiner; Val: ,
Key: noun; Val: cols
Key: cols; Val: a,b,c
Key: is_multicol; Val: a,b,c
Key: modifier; Val: !
Macro: {range:b-z:,}?
Key: joiner; Val: ,
Key: noun; Val: range
Key: col_start; Val: b
Key: is_multicol; Val: b-z
Key: col_stop; Val: z
Key: modifier; Val: ?
Macro: {col:1}?
Key: noun; Val: col
Key: modifier; Val: ?
Key: col; Val: 1
# Working Backup
\{(?P<noun>(?:cols?|range))\:(?:(?P<is_multicol>(?<=cols:)(?P<cols>(?:(?:[a-zA-Z]+|[0-9]+)(?:,(?:[a-zA-Z]+|[0-9]+))+))|(?<=range:)(?P<col_start>(?:[a-zA-Z]+|[0-9]+))\-(?P<col_stop>(?:[a-zA-Z]+|[0-9]+)))?|(?<=col:)(?P<col>(?:[a-zA-Z]+|[0-9]+)))(?(is_multicol)(?:\:(?P<joiner>(?:.)))?)\}(?P<modifier>(?:[\?\!]))?
# Pattern Explination
\{ (?# Macro opening character)
(?P<noun>(?:cols?|range)) (?# 'noun' named-group matcher (col, cols or range))
\: (?# First delimiter between first and second segments)
(?: (?# Start the )
(?P<is_multicol> (?# 'is_multicol' named-group matcher, is positive if any of the nested named-groups are positive)
(?<=cols:) (?# Noun 'cols' named-group matcher)
(?P<cols>(?:(?:[a-zA-Z]+|[0-9]+)(?:,(?:[a-zA-Z]+|[0-9]+))+)) (?# Comma separated list of alpha-numeric characters (must have at least two characters))
|
(?<=range:) (?# Noun 'range' named-group matcher)
(?P<col_start>(?:[a-zA-Z]+|[0-9]+)) (?# The range start index - saved as col_start named-group)
\- (?# Column range index separator)
(?P<col_stop>(?:[a-zA-Z]+|[0-9]+)) (?# The range stop index - saved as col_stop named-group)
)?
| (?# )
(?<=col:) (?# If look-behind match for 'col' is successful...)
(?P<col>(?:[a-zA-Z]+|[0-9]+)) (?# .. Then match for a single column index (alpha OR numeric), save it to named group 'col')
) (?# Close the column(s) matcher)
(?(is_multicol) (?# If the 'is_multicol' named-group has a match (meaning if the noun is cols or range)...)
(?:\:(?P<joiner>(?:.)))? (?# ... Then look for an optional column 'joiner', and save it to the named-group 'joiner')
)
\} (?# Macro closing character)
(?P<modifier>(?:[\?\!]))? (?# Optional character modifier, saved to 'modifier' named group (Current thinking is '?' for optional, '!' for required))
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment